From eae8ffc0fc20997bda6e540b4da448bf00a0d8d7 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Sun, 15 Jan 2023 16:52:19 +0400 Subject: [PATCH 01/18] Add JSON jackson step, Refactor with Yaml, enable endWithEol, features are defined in a Map -> boolean --- lib/build.gradle | 1 + .../glue/json/JsonJacksonFormatterFunc.java | 103 ++++++++++++++++++ .../glue/yaml/YamlJacksonFormatterFunc.java | 77 ++----------- .../diffplug/spotless/json/JacksonConfig.java | 71 ++++++++++++ .../spotless/json/JacksonJsonStep.java | 79 ++++++++++++++ ...lJacksonStep.java => JacksonYamlStep.java} | 31 +++--- .../Jackson.java => json/JacksonJson.java} | 34 ++++-- .../diffplug/spotless/maven/json/Json.java | 4 + .../spotless/maven/yaml/JacksonYaml.java | 60 ++++++++++ .../diffplug/spotless/maven/yaml/Yaml.java | 2 +- .../spotless/maven/json/JsonTest.java | 23 +++- .../spotless/maven/yaml/YamlTest.java | 9 ++ .../json/sortByKeysAfter_Jackson.json | 19 ++++ ...fter_Jackson_noSpaceAfterKeySeparator.json | 19 ++++ .../array_with_bracket.clean_with_eol.yaml | 12 ++ 15 files changed, 441 insertions(+), 103 deletions(-) create mode 100644 lib/src/jackson/java/com/diffplug/spotless/glue/json/JsonJacksonFormatterFunc.java create mode 100644 lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java create mode 100644 lib/src/main/java/com/diffplug/spotless/json/JacksonJsonStep.java rename lib/src/main/java/com/diffplug/spotless/yaml/{YamlJacksonStep.java => JacksonYamlStep.java} (70%) rename plugin-maven/src/main/java/com/diffplug/spotless/maven/{yaml/Jackson.java => json/JacksonJson.java} (51%) create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java create mode 100644 testlib/src/main/resources/json/sortByKeysAfter_Jackson.json create mode 100644 testlib/src/main/resources/json/sortByKeysAfter_Jackson_noSpaceAfterKeySeparator.json create mode 100644 testlib/src/main/resources/yaml/array_with_bracket.clean_with_eol.yaml diff --git a/lib/build.gradle b/lib/build.gradle index 3ef2064765..3c36aa0188 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -57,6 +57,7 @@ dependencies { palantirJavaFormatCompileOnly 'com.palantir.javaformat:palantir-java-format:1.1.0' // this version needs to stay compilable against Java 8 for CI Job testNpm // used jackson-based formatters + jacksonCompileOnly 'com.fasterxml.jackson.core:jackson-databind:2.14.1' jacksonCompileOnly 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.1' String VER_KTFMT = '0.42' diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JsonJacksonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JsonJacksonFormatterFunc.java new file mode 100644 index 0000000000..0a13ab6626 --- /dev/null +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JsonJacksonFormatterFunc.java @@ -0,0 +1,103 @@ +/* + * Copyright 2021-2023 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.glue.json; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.json.JacksonConfig; + +/** + * A {@link FormatterFunc} based on Jackson library + */ +// https://github.com/FasterXML/jackson-dataformats-text/issues/372 +public class JsonJacksonFormatterFunc implements FormatterFunc { + private JacksonConfig jacksonConfig; + + public JsonJacksonFormatterFunc(JacksonConfig jacksonConfig) { + this.jacksonConfig = jacksonConfig; + } + + @Override + public String apply(String input) throws Exception { + ObjectMapper objectMapper = makeObjectMapper(); + + return format(objectMapper, input); + } + + /** + * @return a {@link JsonFactory}. May be overridden to handle alternative formats. + * @see jackson-dataformats-text + */ + protected JsonFactory makeJsonFactory() { + return new JsonFactory(); + } + + protected ObjectMapper makeObjectMapper() { + JsonFactory jsonFactory = makeJsonFactory(); + ObjectMapper objectMapper = new ObjectMapper(jsonFactory); + + // Configure the ObjectMapper + // https://github.com/FasterXML/jackson-databind#commonly-used-features + jacksonConfig.getFeatureToToggle().forEach((rawFeature, toggle) -> { + // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection + SerializationFeature feature = SerializationFeature.valueOf(rawFeature); + + objectMapper.configure(feature, toggle); + }); + + return objectMapper; + } + + protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { + // We may consider adding manually an initial '---' prefix to help management of multiple documents + // if (!input.trim().startsWith("---")) { + // input = "---" + "\n" + input; + // } + + try { + // https://stackoverflow.com/questions/25222327/deserialize-pojos-from-multiple-yaml-documents-in-a-single-file-in-jackson + // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-375328648 + // 2023-01: For now, we get 'Cannot deserialize value of type `com.fasterxml.jackson.databind.node.ObjectNode` from Array value' + // JsonParser yamlParser = objectMapper.getFactory().createParser(input); + // List docs = objectMapper.readValues(yamlParser, ObjectNode.class).readAll(); + // return objectMapper.writeValueAsString(docs); + + // 2023-01: This returns JSON instead of YAML + // This will transit with a JsonNode + // A JsonNode may keep the comments from the input node + // JsonNode jsonNode = objectMapper.readTree(input); + //Not 'toPrettyString' as one could require no INDENT_OUTPUT + // return jsonNode.toPrettyString(); + ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); + String outputFromjackson = objectMapper.writeValueAsString(objectNode); + + if (jacksonConfig.isEndWithEol() && !outputFromjackson.endsWith("\n")) { + outputFromjackson += "\n"; + } + + return outputFromjackson; + } catch (JsonProcessingException e) { + throw new AssertionError("Unable to format. input='" + input + "'", e); + } + } +} diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/YamlJacksonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/YamlJacksonFormatterFunc.java index 30cf538159..eda2675985 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/YamlJacksonFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/YamlJacksonFormatterFunc.java @@ -15,83 +15,20 @@ */ package com.diffplug.spotless.glue.yaml; -import java.io.IOException; -import java.util.List; +import com.diffplug.spotless.glue.json.JsonJacksonFormatterFunc; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.json.JacksonConfig; -public class YamlJacksonFormatterFunc implements FormatterFunc { - private List enabledFeatures; - private List disabledFeatures; +public class YamlJacksonFormatterFunc extends JsonJacksonFormatterFunc { - public YamlJacksonFormatterFunc(List enabledFeatures, List disabledFeatures) { - this.enabledFeatures = enabledFeatures; - this.disabledFeatures = disabledFeatures; + public YamlJacksonFormatterFunc(JacksonConfig jacksonConfig) { + super(jacksonConfig); } @Override - public String apply(String input) throws Exception { - ObjectMapper objectMapper = makeObjectMapper(); - - return format(objectMapper, input); - } - - protected ObjectMapper makeObjectMapper() { - YAMLFactory yamlFactory = new YAMLFactory(); - ObjectMapper objectMapper = new ObjectMapper(yamlFactory); - - // Configure the ObjectMapper - // https://github.com/FasterXML/jackson-databind#commonly-used-features - for (String rawFeature : enabledFeatures) { - // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection - SerializationFeature feature = SerializationFeature.valueOf(rawFeature); - - objectMapper.enable(feature); - } - - for (String rawFeature : disabledFeatures) { - // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection - SerializationFeature feature = SerializationFeature.valueOf(rawFeature); - - objectMapper.disable(feature); - } - return objectMapper; - } - - protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { - // We may consider adding manually an initial '---' prefix to help management of multiple documents - // if (!input.trim().startsWith("---")) { - // input = "---" + "\n" + input; - // } - - try { - // https://stackoverflow.com/questions/25222327/deserialize-pojos-from-multiple-yaml-documents-in-a-single-file-in-jackson - // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-375328648 - // 2023-01: For now, we get 'Cannot deserialize value of type `com.fasterxml.jackson.databind.node.ObjectNode` from Array value' - // JsonParser yamlParser = objectMapper.getFactory().createParser(input); - // List docs = objectMapper.readValues(yamlParser, ObjectNode.class).readAll(); - // return objectMapper.writeValueAsString(docs); - - // 2023-01: This returns JSON instead of YAML - // This will transit with a JsonNode - // A JsonNode may keep the comments from the input node - // JsonNode jsonNode = objectMapper.readTree(input); - //Not 'toPrettyString' as one could require no INDENT_OUTPUT - // return jsonNode.toPrettyString(); - ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); - return objectMapper.writeValueAsString(objectNode); - } catch (JsonProcessingException e) { - throw new AssertionError("Unable to format YAML. input='" + input + "'", e); - } + protected YAMLFactory makeJsonFactory() { + return new YAMLFactory(); } - - // Spotbugs - private static class ObjectNodeTypeReference extends TypeReference {} } diff --git a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java new file mode 100644 index 0000000000..526e235eb7 --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java @@ -0,0 +1,71 @@ +/* + * Copyright 2023 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; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * A DTO holding the options for Jackson-based formatters + */ +public class JacksonConfig { + + private static final Map DEFAULT_FEATURE_TOGGLES; + + static { + Map defaultFeatureToggles = new LinkedHashMap<>(); + // We activate by default the PrettyPrinter from Jackson + defaultFeatureToggles.put("INDENT_OUTPUT", true); + DEFAULT_FEATURE_TOGGLES = defaultFeatureToggles; + } + + protected Map featureToToggle; + + // https://github.com/revelc/formatter-maven-plugin/pull/405 + protected boolean endWithEol = false; + + // https://github.com/revelc/formatter-maven-plugin/pull/280 + protected boolean spaceBeforeSeparator = false; + + public Map getFeatureToToggle() { + return Collections.unmodifiableMap(featureToToggle); + } + + public void setFeatureToToggle(Map featureToToggle) { + this.featureToToggle = featureToToggle; + } + + public void appendFeatureToToggle(Map features) { + this.featureToToggle.putAll(features); + } + + public boolean isEndWithEol() { + return endWithEol; + } + + public void setEndWithEol(boolean endWithEol) { + this.endWithEol = endWithEol; + } + + public boolean isSpaceBeforeSeparator() { + return spaceBeforeSeparator; + } + + public void setSpaceBeforeSeparator(boolean spaceBeforeSeparator) { + this.spaceBeforeSeparator = spaceBeforeSeparator; + } +} diff --git a/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonStep.java b/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonStep.java new file mode 100644 index 0000000000..0fe1ab057b --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonStep.java @@ -0,0 +1,79 @@ +/* + * Copyright 2021-2023 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; + +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Objects; + +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.JarState; +import com.diffplug.spotless.Provisioner; + +/** + * Simple YAML formatter which reformats the file according to Jackson YAMLFactory. + */ +// https://stackoverflow.com/questions/14515994/convert-json-string-to-pretty-print-json-output-using-jackson +public class JacksonJsonStep { + static final String MAVEN_COORDINATE = "com.fasterxml.jackson.core:jackson-databind:"; + // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind + static final String DEFAULT_VERSION = "2.14.1"; + + private JacksonJsonStep() {} + + public static String defaultVersion() { + return DEFAULT_VERSION; + } + + public static FormatterStep create(JacksonConfig jacksonConfig, + String jacksonVersion, + Provisioner provisioner) { + Objects.requireNonNull(provisioner, "provisioner cannot be null"); + return FormatterStep.createLazy("json", + () -> new State(jacksonConfig, jacksonVersion, provisioner), + State::toFormatter); + } + + public static FormatterStep create(Provisioner provisioner) { + return create(new JacksonConfig(), defaultVersion(), provisioner); + } + + private static final class State implements Serializable { + private static final long serialVersionUID = 1L; + + private final JacksonConfig jacksonConfig; + + private final JarState jarState; + + private State(JacksonConfig jacksonConfig, + String jacksonVersion, + Provisioner provisioner) throws IOException { + this.jacksonConfig = jacksonConfig; + + this.jarState = JarState.from(JacksonJsonStep.MAVEN_COORDINATE + jacksonVersion, provisioner); + } + + FormatterFunc toFormatter() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, + InstantiationException, IllegalAccessException { + Class formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.json.JacksonJsonFormatterFunc"); + Constructor constructor = formatterFunc.getConstructor(JacksonConfig.class); + return (FormatterFunc) constructor.newInstance(jacksonConfig); + } + } +} diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java similarity index 70% rename from lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java rename to lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java index db2525ab97..944d90e6c9 100644 --- a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java +++ b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java @@ -19,67 +19,62 @@ import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.util.Arrays; -import java.util.List; import java.util.Objects; import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.JarState; import com.diffplug.spotless.Provisioner; +import com.diffplug.spotless.json.JacksonConfig; /** * Simple YAML formatter which reformats the file according to Jackson YAMLFactory. */ // https://stackoverflow.com/questions/14515994/convert-json-string-to-pretty-print-json-output-using-jackson -public class YamlJacksonStep { +public class JacksonYamlStep { static final String MAVEN_COORDINATE = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:"; // https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml static final String DEFAULT_VERSION = "2.14.1"; - private YamlJacksonStep() {} + private JacksonYamlStep() {} public static String defaultVersion() { return DEFAULT_VERSION; } - public static FormatterStep create(List enabledFeatures, - List disabledFeatures, + public static FormatterStep create(JacksonConfig jacksonConfig, String jacksonVersion, Provisioner provisioner) { Objects.requireNonNull(provisioner, "provisioner cannot be null"); return FormatterStep.createLazy("yaml", - () -> new State(enabledFeatures, disabledFeatures, jacksonVersion, provisioner), + () -> new State(jacksonConfig, jacksonVersion, provisioner), State::toFormatter); } public static FormatterStep create(Provisioner provisioner) { - return create(Arrays.asList("INDENT_OUTPUT"), Arrays.asList(), defaultVersion(), provisioner); + return create(new JacksonConfig(), defaultVersion(), provisioner); } private static final class State implements Serializable { private static final long serialVersionUID = 1L; - private final List enabledFeatures; - private final List disabledFeatures; + private final JacksonConfig jacksonConfig; private final JarState jarState; - private State(List enabledFeatures, - List disabledFeatures, + private State(JacksonConfig jacksonConfig, String jacksonVersion, Provisioner provisioner) throws IOException { - this.enabledFeatures = enabledFeatures; - this.disabledFeatures = disabledFeatures; + this.jacksonConfig = jacksonConfig; - this.jarState = JarState.from(YamlJacksonStep.MAVEN_COORDINATE + jacksonVersion, provisioner); + this.jarState = JarState.from(JacksonYamlStep.MAVEN_COORDINATE + jacksonVersion, provisioner); } FormatterFunc toFormatter() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { - Class formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.yaml.YamlJacksonFormatterFunc"); - Constructor constructor = formatterFunc.getConstructor(List.class, List.class); - return (FormatterFunc) constructor.newInstance(enabledFeatures, disabledFeatures); + Class formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.yaml.JacksonYamlFormatterFunc"); + Constructor constructor = formatterFunc.getConstructor(JacksonConfig.class); + return (FormatterFunc) constructor.newInstance(jacksonConfig); } } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Jackson.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java similarity index 51% rename from plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Jackson.java rename to plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java index 2bc7617a38..cf03ef21ca 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Jackson.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java @@ -13,34 +13,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.diffplug.spotless.maven.yaml; +package com.diffplug.spotless.maven.json; -import java.util.Arrays; -import java.util.List; +import java.util.Collections; +import java.util.Map; import org.apache.maven.plugins.annotations.Parameter; import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.json.JacksonConfig; +import com.diffplug.spotless.json.JacksonJsonStep; +import com.diffplug.spotless.maven.FormatterFactory; import com.diffplug.spotless.maven.FormatterStepConfig; import com.diffplug.spotless.maven.FormatterStepFactory; -import com.diffplug.spotless.yaml.YamlJacksonStep; -public class Jackson implements FormatterStepFactory { +/** + * A {@link FormatterFactory} implementation that corresponds to {@code ...} configuration element. + */ +public class JacksonJson implements FormatterStepFactory { @Parameter - private String version = YamlJacksonStep.defaultVersion(); + String version = JacksonJsonStep.defaultVersion(); @Parameter - private String[] enabledFeatures = new String[]{"INDENT_OUTPUT"}; + boolean endWithEol = new JacksonConfig().isEndWithEol(); @Parameter - private String[] disabledFeatures = new String[0]; + private Map features = Collections.emptyMap(); @Override public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { - List enabledFeaturesAsList = Arrays.asList(enabledFeatures); - List disabledFeaturesAsList = Arrays.asList(disabledFeatures); - return YamlJacksonStep - .create(enabledFeaturesAsList, disabledFeaturesAsList, version, stepConfig.getProvisioner()); + JacksonConfig jacksonConfig = new JacksonConfig(); + + if (features != null) { + jacksonConfig.appendFeatureToToggle(features); + } + jacksonConfig.setEndWithEol(endWithEol); + + return JacksonJsonStep + .create(jacksonConfig, version, stepConfig.getProvisioner()); } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Json.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Json.java index c326525d0c..852088278a 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Json.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Json.java @@ -44,4 +44,8 @@ public void addGson(Gson gson) { addStepFactory(gson); } + public void addJackson(JacksonJson jackson) { + addStepFactory(jackson); + } + } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java new file mode 100644 index 0000000000..d3d9558cf4 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java @@ -0,0 +1,60 @@ +/* + * Copyright 2023 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.maven.yaml; + +import java.util.Collections; +import java.util.Map; + +import com.diffplug.spotless.maven.FormatterFactory; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.json.JacksonConfig; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; +import com.diffplug.spotless.yaml.JacksonYamlStep; + +/** + * A {@link FormatterFactory} implementation that corresponds to {@code ...} configuration element. + */ +public class JacksonYaml implements FormatterStepFactory { + + @Parameter + private String version = JacksonYamlStep.defaultVersion(); + + @Parameter + boolean endWithEol = new JacksonConfig().isEndWithEol(); + + @Parameter + boolean spaceBeforeSeparator = new JacksonConfig().isSpaceBeforeSeparator(); + + @Parameter + private Map features = Collections.emptyMap(); + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { + JacksonConfig jacksonConfig = new JacksonConfig(); + + if (features != null) { + jacksonConfig.appendFeatureToToggle(features); + } + jacksonConfig.setEndWithEol(endWithEol); + + return JacksonYamlStep + .create(jacksonConfig, version, stepConfig.getProvisioner()); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Yaml.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Yaml.java index 6cba1b2ebd..a6ceaaa592 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Yaml.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Yaml.java @@ -34,7 +34,7 @@ public String licenseHeaderDelimiter() { return null; } - public void addJackson(Jackson jackson) { + public void addJackson(JacksonYaml jackson) { addStepFactory(jackson); } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java index e492109faa..90b3a2f077 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java @@ -58,8 +58,6 @@ public void testFormatJson_WithGson_sortByKeys() throws Exception { setFile("json_test.json").toResource("json/sortByKeysBefore.json"); String output = mavenRunner().withArguments("spotless:apply").runNoError().output(); - LOGGER.error(output); - System.err.println(output); assertFile("json_test.json").sameAsResource("json/sortByKeysAfter.json"); } @@ -72,4 +70,25 @@ public void testFormatJson_WithGson_defaultConfig_nestedObject() throws Exceptio assertFile("json_test.json").sameAsResource("json/nestedObjectAfter.json"); } + + @Test + public void testFormatJson_WithJackson_sortByKeys() throws Exception { + writePomWithJsonSteps("true"); + + setFile("json_test.json").toResource("json/sortByKeysBefore.json"); + + String output = mavenRunner().withArguments("spotless:apply").runNoError().output(); + assertFile("json_test.json").sameAsResource("json/sortByKeysAfter.json"); + } + + @Test + public void testFormatJson_WithJackson_sortByKeys_noSpaceAfterKeySeparator() throws Exception { + writePomWithJsonSteps("falsetrue"); + + setFile("json_test.json").toResource("json/sortByKeysBefore.json"); + + String output = mavenRunner().withArguments("spotless:apply").runNoError().output(); + assertFile("json_test.json").sameAsResource("json/sortByKeysAfter.json"); + } + } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java index b5a417c536..15366ab2e6 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java @@ -48,6 +48,15 @@ public void testFormatYaml_WithJackson_defaultConfig_arrayBrackets() throws Exce assertFile("yaml_test.yaml").sameAsResource("yaml/array_with_bracket.clean.yaml"); } + @Test + public void testFormatYaml_WithJackson_defaultConfig_arrayBrackets_withEol() throws Exception { + writePomWithYamlSteps("true"); + + setFile("yaml_test.yaml").toResource("yaml/array_with_bracket.yaml"); + mavenRunner().withArguments("spotless:apply").runNoError(); + assertFile("yaml_test.yaml").sameAsResource("yaml/array_with_bracket.clean_with_eol.yaml"); + } + @Test public void testFormatYaml_WithJackson_defaultConfig_multipleDocuments() throws Exception { writePomWithYamlSteps(""); diff --git a/testlib/src/main/resources/json/sortByKeysAfter_Jackson.json b/testlib/src/main/resources/json/sortByKeysAfter_Jackson.json new file mode 100644 index 0000000000..c4a48de2f2 --- /dev/null +++ b/testlib/src/main/resources/json/sortByKeysAfter_Jackson.json @@ -0,0 +1,19 @@ +{ + "A": 1, + "X": 2, + "_arraysNotSorted": [ + 3, + 2, + 1 + ], + "a": 3, + "c": 4, + "x": 5, + "z": { + "A": 1, + "X": 2, + "a": 3, + "c": 4, + "x": 5 + } +} diff --git a/testlib/src/main/resources/json/sortByKeysAfter_Jackson_noSpaceAfterKeySeparator.json b/testlib/src/main/resources/json/sortByKeysAfter_Jackson_noSpaceAfterKeySeparator.json new file mode 100644 index 0000000000..c4a48de2f2 --- /dev/null +++ b/testlib/src/main/resources/json/sortByKeysAfter_Jackson_noSpaceAfterKeySeparator.json @@ -0,0 +1,19 @@ +{ + "A": 1, + "X": 2, + "_arraysNotSorted": [ + 3, + 2, + 1 + ], + "a": 3, + "c": 4, + "x": 5, + "z": { + "A": 1, + "X": 2, + "a": 3, + "c": 4, + "x": 5 + } +} diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean_with_eol.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean_with_eol.yaml new file mode 100644 index 0000000000..6080ba1f82 --- /dev/null +++ b/testlib/src/main/resources/yaml/array_with_bracket.clean_with_eol.yaml @@ -0,0 +1,12 @@ +--- +episodes: +- 1 +- 2 +- 3 +- 4 +- 5 +- 6 +- 7 +best-jedi: + name: "Obi-Wan" + side: "light" From 65e74655e9191d1c891cafb6e3c5683da35bb041 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Mon, 16 Jan 2023 21:17:46 +0400 Subject: [PATCH 02/18] Add doc, Improve tests --- CHANGES.md | 2 + ...unc.java => JacksonJsonFormatterFunc.java} | 53 +++++++++++++-- .../glue/yaml/JacksonYamlFormatterFunc.java | 66 +++++++++++++++++++ .../glue/yaml/YamlJacksonFormatterFunc.java | 34 ---------- .../diffplug/spotless/json/JacksonConfig.java | 27 ++++---- plugin-maven/CHANGES.md | 5 ++ plugin-maven/README.md | 12 ++-- .../spotless/maven/json/JacksonJson.java | 10 ++- .../spotless/maven/yaml/JacksonYaml.java | 14 ++-- .../spotless/maven/json/JsonTest.java | 9 ++- .../spotless/maven/yaml/YamlTest.java | 6 +- ...After_Jackson_spaceAfterKeySeparator.json} | 0 ...h_bracket.clean.spaceBeforeSeparator.yaml} | 2 +- 13 files changed, 156 insertions(+), 84 deletions(-) rename lib/src/jackson/java/com/diffplug/spotless/glue/json/{JsonJacksonFormatterFunc.java => JacksonJsonFormatterFunc.java} (70%) create mode 100644 lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java delete mode 100644 lib/src/jackson/java/com/diffplug/spotless/glue/yaml/YamlJacksonFormatterFunc.java rename testlib/src/main/resources/json/{sortByKeysAfter_Jackson_noSpaceAfterKeySeparator.json => sortByKeysAfter_Jackson_spaceAfterKeySeparator.json} (100%) rename testlib/src/main/resources/yaml/{array_with_bracket.clean_with_eol.yaml => array_with_bracket.clean.spaceBeforeSeparator.yaml} (81%) diff --git a/CHANGES.md b/CHANGES.md index c08ca86796..fd10d2c14e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,8 @@ 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] +### Changes +* Rename `YamlJacksonStep` into `JacksonYamlStep` while normalizing Jackson usage ([#1492](https://github.com/diffplug/spotless/pull/1492)) ## [2.32.0] - 2023-01-13 ### Added diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JsonJacksonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java similarity index 70% rename from lib/src/jackson/java/com/diffplug/spotless/glue/json/JsonJacksonFormatterFunc.java rename to lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java index 0a13ab6626..c19e56b549 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JsonJacksonFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java @@ -16,9 +16,14 @@ package com.diffplug.spotless.glue.json; import java.io.IOException; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.util.DefaultIndenter; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.core.util.Separators; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -30,10 +35,10 @@ * A {@link FormatterFunc} based on Jackson library */ // https://github.com/FasterXML/jackson-dataformats-text/issues/372 -public class JsonJacksonFormatterFunc implements FormatterFunc { +public class JacksonJsonFormatterFunc implements FormatterFunc { private JacksonConfig jacksonConfig; - public JsonJacksonFormatterFunc(JacksonConfig jacksonConfig) { + public JacksonJsonFormatterFunc(JacksonConfig jacksonConfig) { this.jacksonConfig = jacksonConfig; } @@ -56,6 +61,8 @@ protected ObjectMapper makeObjectMapper() { JsonFactory jsonFactory = makeJsonFactory(); ObjectMapper objectMapper = new ObjectMapper(jsonFactory); + objectMapper.setDefaultPrettyPrinter(makePrinter()); + // Configure the ObjectMapper // https://github.com/FasterXML/jackson-databind#commonly-used-features jacksonConfig.getFeatureToToggle().forEach((rawFeature, toggle) -> { @@ -68,6 +75,44 @@ protected ObjectMapper makeObjectMapper() { return objectMapper; } + protected DefaultPrettyPrinter makePrinter() { + boolean spaceBeforeSeparator = jacksonConfig.isSpaceBeforeSeparator(); + + DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(getIndentation(), "\n"); + DefaultPrettyPrinter printer = new DefaultPrettyPrinter() { + private static final long serialVersionUID = 1L; + + @Override + public DefaultPrettyPrinter createInstance() { + return new DefaultPrettyPrinter(this); + } + + @Override + public DefaultPrettyPrinter withSeparators(Separators separators) { + this._separators = separators; + if (spaceBeforeSeparator) { + this._objectFieldValueSeparatorWithSpaces = " " + separators.getObjectFieldValueSeparator() + " "; + } else { + this._objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSeparator() + " "; + } + return this; + } + }; + + printer.indentObjectsWith(indenter); + printer.indentArraysWith(indenter); + return printer; + } + + protected String getIndentation() { + int indentSpaces = jacksonConfig.getIndentSpaces(); + if (indentSpaces < 0) { + return "\t"; + } else { + return IntStream.range(0, indentSpaces).mapToObj(i -> "").collect(Collectors.joining()); + } + } + protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { // We may consider adding manually an initial '---' prefix to help management of multiple documents // if (!input.trim().startsWith("---")) { @@ -91,10 +136,6 @@ protected String format(ObjectMapper objectMapper, String input) throws IllegalA ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); String outputFromjackson = objectMapper.writeValueAsString(objectNode); - if (jacksonConfig.isEndWithEol() && !outputFromjackson.endsWith("\n")) { - outputFromjackson += "\n"; - } - return outputFromjackson; } catch (JsonProcessingException e) { throw new AssertionError("Unable to format. input='" + input + "'", e); diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java new file mode 100644 index 0000000000..6a471a884c --- /dev/null +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021-2023 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.glue.yaml; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; + +import com.diffplug.spotless.glue.json.JacksonJsonFormatterFunc; +import com.diffplug.spotless.json.JacksonConfig; + +public class JacksonYamlFormatterFunc extends JacksonJsonFormatterFunc { + + public JacksonYamlFormatterFunc(JacksonConfig jacksonConfig) { + super(jacksonConfig); + } + + @Override + protected YAMLFactory makeJsonFactory() { + return new YAMLFactory(); + } + + @Override + protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { + // We may consider adding manually an initial '---' prefix to help management of multiple documents + // if (!input.trim().startsWith("---")) { + // input = "---" + "\n" + input; + // } + + try { + // https://stackoverflow.com/questions/25222327/deserialize-pojos-from-multiple-yaml-documents-in-a-single-file-in-jackson + // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-375328648 + // 2023-01: For now, we get 'Cannot deserialize value of type `com.fasterxml.jackson.databind.node.ObjectNode` from Array value' + // JsonParser yamlParser = objectMapper.getFactory().createParser(input); + // List docs = objectMapper.readValues(yamlParser, ObjectNode.class).readAll(); + // return objectMapper.writeValueAsString(docs); + + // A JsonNode may keep the comments from the input node + // JsonNode jsonNode = objectMapper.readTree(input); + //Not 'toPrettyString' as one could require no INDENT_OUTPUT + // return jsonNode.toPrettyString(); + ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); + String outputFromjackson = objectMapper.writeValueAsString(objectNode); + + return outputFromjackson; + } catch (JsonProcessingException e) { + throw new AssertionError("Unable to format. input='" + input + "'", e); + } + } +} diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/YamlJacksonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/YamlJacksonFormatterFunc.java deleted file mode 100644 index eda2675985..0000000000 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/YamlJacksonFormatterFunc.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2021-2023 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.glue.yaml; - -import com.diffplug.spotless.glue.json.JsonJacksonFormatterFunc; - -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; - -import com.diffplug.spotless.json.JacksonConfig; - -public class YamlJacksonFormatterFunc extends JsonJacksonFormatterFunc { - - public YamlJacksonFormatterFunc(JacksonConfig jacksonConfig) { - super(jacksonConfig); - } - - @Override - protected YAMLFactory makeJsonFactory() { - return new YAMLFactory(); - } -} diff --git a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java index 526e235eb7..2fadf31d78 100644 --- a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java +++ b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java @@ -15,6 +15,7 @@ */ package com.diffplug.spotless.json; +import java.io.Serializable; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; @@ -22,7 +23,7 @@ /** * A DTO holding the options for Jackson-based formatters */ -public class JacksonConfig { +public class JacksonConfig implements Serializable { private static final Map DEFAULT_FEATURE_TOGGLES; @@ -33,14 +34,14 @@ public class JacksonConfig { DEFAULT_FEATURE_TOGGLES = defaultFeatureToggles; } - protected Map featureToToggle; - - // https://github.com/revelc/formatter-maven-plugin/pull/405 - protected boolean endWithEol = false; + protected Map featureToToggle = new LinkedHashMap<>(); // https://github.com/revelc/formatter-maven-plugin/pull/280 + // By default, Jackson adds a ' ' before separator, which is not standard with most IDE/JSON libraries protected boolean spaceBeforeSeparator = false; + // protected int indentSpaces; + public Map getFeatureToToggle() { return Collections.unmodifiableMap(featureToToggle); } @@ -53,14 +54,6 @@ public void appendFeatureToToggle(Map features) { this.featureToToggle.putAll(features); } - public boolean isEndWithEol() { - return endWithEol; - } - - public void setEndWithEol(boolean endWithEol) { - this.endWithEol = endWithEol; - } - public boolean isSpaceBeforeSeparator() { return spaceBeforeSeparator; } @@ -68,4 +61,12 @@ public boolean isSpaceBeforeSeparator() { public void setSpaceBeforeSeparator(boolean spaceBeforeSeparator) { this.spaceBeforeSeparator = spaceBeforeSeparator; } + + // public int getIndentSpaces() { + // return indentSpaces; + // } + + // public void setIndentSpaces(int indentSpaces) { + // this.indentSpaces = indentSpaces; + // } } diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 05cc349e9f..d6326cba12 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -3,6 +3,11 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] +### Added +* Introduce `` ([#1492](https://github.com/diffplug/spotless/pull/1492)) + * **POTENTIALLY BREAKING** `JacksonYaml` is now configured with a `Map` to configure features +* Jackson (JSON and YAML) has new `spaceBeforeSeparator` option + * **POTENTIALLY BREAKING** `spaceBeforeSeparator` is defaulted to false while the formatter was behaving with `true` ## [2.30.0] - 2023-01-13 ### Added diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 2a455dfe07..6dca992591 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -924,12 +924,12 @@ Uses Jackson and YAMLFactory to pretty print objects: ```xml 2.14.1 - - INDENT_OUTPUT - - - DEFAULT_HAS_NO_DISABLED_FEATURE - + + true + false + true|false + + false ``` diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java index cf03ef21ca..31c59a5f81 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java @@ -33,10 +33,10 @@ public class JacksonJson implements FormatterStepFactory { @Parameter - String version = JacksonJsonStep.defaultVersion(); + private String version = JacksonJsonStep.defaultVersion(); @Parameter - boolean endWithEol = new JacksonConfig().isEndWithEol(); + private boolean spaceBeforeSeparator = new JacksonConfig().isSpaceBeforeSeparator(); @Parameter private Map features = Collections.emptyMap(); @@ -45,10 +45,8 @@ public class JacksonJson implements FormatterStepFactory { public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { JacksonConfig jacksonConfig = new JacksonConfig(); - if (features != null) { - jacksonConfig.appendFeatureToToggle(features); - } - jacksonConfig.setEndWithEol(endWithEol); + jacksonConfig.appendFeatureToToggle(features); + jacksonConfig.setSpaceBeforeSeparator(spaceBeforeSeparator); return JacksonJsonStep .create(jacksonConfig, version, stepConfig.getProvisioner()); diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java index d3d9558cf4..1cd23bc3cc 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java @@ -18,12 +18,11 @@ import java.util.Collections; import java.util.Map; -import com.diffplug.spotless.maven.FormatterFactory; - import org.apache.maven.plugins.annotations.Parameter; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.json.JacksonConfig; +import com.diffplug.spotless.maven.FormatterFactory; import com.diffplug.spotless.maven.FormatterStepConfig; import com.diffplug.spotless.maven.FormatterStepFactory; import com.diffplug.spotless.yaml.JacksonYamlStep; @@ -37,10 +36,7 @@ public class JacksonYaml implements FormatterStepFactory { private String version = JacksonYamlStep.defaultVersion(); @Parameter - boolean endWithEol = new JacksonConfig().isEndWithEol(); - - @Parameter - boolean spaceBeforeSeparator = new JacksonConfig().isSpaceBeforeSeparator(); + private boolean spaceBeforeSeparator = new JacksonConfig().isSpaceBeforeSeparator(); @Parameter private Map features = Collections.emptyMap(); @@ -49,10 +45,8 @@ public class JacksonYaml implements FormatterStepFactory { public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { JacksonConfig jacksonConfig = new JacksonConfig(); - if (features != null) { - jacksonConfig.appendFeatureToToggle(features); - } - jacksonConfig.setEndWithEol(endWithEol); + jacksonConfig.appendFeatureToToggle(features); + jacksonConfig.setSpaceBeforeSeparator(spaceBeforeSeparator); return JacksonYamlStep .create(jacksonConfig, version, stepConfig.getProvisioner()); diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java index 90b3a2f077..b263be8173 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java @@ -70,7 +70,6 @@ public void testFormatJson_WithGson_defaultConfig_nestedObject() throws Exceptio assertFile("json_test.json").sameAsResource("json/nestedObjectAfter.json"); } - @Test public void testFormatJson_WithJackson_sortByKeys() throws Exception { writePomWithJsonSteps("true"); @@ -78,17 +77,17 @@ public void testFormatJson_WithJackson_sortByKeys() throws Exception { setFile("json_test.json").toResource("json/sortByKeysBefore.json"); String output = mavenRunner().withArguments("spotless:apply").runNoError().output(); - assertFile("json_test.json").sameAsResource("json/sortByKeysAfter.json"); + assertFile("json_test.json").sameAsResource("json/sortByKeysAfter_Jackson.json"); } @Test - public void testFormatJson_WithJackson_sortByKeys_noSpaceAfterKeySeparator() throws Exception { - writePomWithJsonSteps("falsetrue"); + public void testFormatJson_WithJackson_sortByKeys_spaceAfterKeySeparator() throws Exception { + writePomWithJsonSteps("truetrue"); setFile("json_test.json").toResource("json/sortByKeysBefore.json"); String output = mavenRunner().withArguments("spotless:apply").runNoError().output(); - assertFile("json_test.json").sameAsResource("json/sortByKeysAfter.json"); + assertFile("json_test.json").sameAsResource("json/sortByKeysAfter_Jackson_spaceAfterKeySeparator.json"); } } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java index 15366ab2e6..51f8da99f4 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java @@ -49,12 +49,12 @@ public void testFormatYaml_WithJackson_defaultConfig_arrayBrackets() throws Exce } @Test - public void testFormatYaml_WithJackson_defaultConfig_arrayBrackets_withEol() throws Exception { - writePomWithYamlSteps("true"); + public void testFormatYaml_WithJackson_defaultConfig_arrayBrackets_spaceBeforeSeparator() throws Exception { + writePomWithYamlSteps("true"); setFile("yaml_test.yaml").toResource("yaml/array_with_bracket.yaml"); mavenRunner().withArguments("spotless:apply").runNoError(); - assertFile("yaml_test.yaml").sameAsResource("yaml/array_with_bracket.clean_with_eol.yaml"); + assertFile("yaml_test.yaml").sameAsResource("yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml"); } @Test diff --git a/testlib/src/main/resources/json/sortByKeysAfter_Jackson_noSpaceAfterKeySeparator.json b/testlib/src/main/resources/json/sortByKeysAfter_Jackson_spaceAfterKeySeparator.json similarity index 100% rename from testlib/src/main/resources/json/sortByKeysAfter_Jackson_noSpaceAfterKeySeparator.json rename to testlib/src/main/resources/json/sortByKeysAfter_Jackson_spaceAfterKeySeparator.json diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean_with_eol.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml similarity index 81% rename from testlib/src/main/resources/yaml/array_with_bracket.clean_with_eol.yaml rename to testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml index 6080ba1f82..c6f891b9de 100644 --- a/testlib/src/main/resources/yaml/array_with_bracket.clean_with_eol.yaml +++ b/testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml @@ -9,4 +9,4 @@ episodes: - 7 best-jedi: name: "Obi-Wan" - side: "light" + side: "light" \ No newline at end of file From f05126de68661f584b1b5865b406f35f700ae2e5 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Mon, 16 Jan 2023 23:02:39 +0400 Subject: [PATCH 03/18] Fix Spotbugs --- .../glue/json/JacksonJsonFormatterFunc.java | 79 ++++++++----------- .../diffplug/spotless/json/JacksonConfig.java | 1 + 2 files changed, 35 insertions(+), 45 deletions(-) diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java index c19e56b549..c44ff0d0d1 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java @@ -16,8 +16,6 @@ package com.diffplug.spotless.glue.json; import java.io.IOException; -import java.util.stream.Collectors; -import java.util.stream.IntStream; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonProcessingException; @@ -79,25 +77,7 @@ protected DefaultPrettyPrinter makePrinter() { boolean spaceBeforeSeparator = jacksonConfig.isSpaceBeforeSeparator(); DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(getIndentation(), "\n"); - DefaultPrettyPrinter printer = new DefaultPrettyPrinter() { - private static final long serialVersionUID = 1L; - - @Override - public DefaultPrettyPrinter createInstance() { - return new DefaultPrettyPrinter(this); - } - - @Override - public DefaultPrettyPrinter withSeparators(Separators separators) { - this._separators = separators; - if (spaceBeforeSeparator) { - this._objectFieldValueSeparatorWithSpaces = " " + separators.getObjectFieldValueSeparator() + " "; - } else { - this._objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSeparator() + " "; - } - return this; - } - }; + DefaultPrettyPrinter printer = new SpotlessDefaultPrettyPrinter(spaceBeforeSeparator); printer.indentObjectsWith(indenter); printer.indentArraysWith(indenter); @@ -105,34 +85,18 @@ public DefaultPrettyPrinter withSeparators(Separators separators) { } protected String getIndentation() { - int indentSpaces = jacksonConfig.getIndentSpaces(); - if (indentSpaces < 0) { - return "\t"; - } else { - return IntStream.range(0, indentSpaces).mapToObj(i -> "").collect(Collectors.joining()); - } + // DefaultIndenter default constructor relies on this + return " "; + // int indentSpaces = jacksonConfig.getIndentSpaces(); + // if (indentSpaces < 0) { + // return "\t"; + // } else { + // return IntStream.range(0, indentSpaces).mapToObj(i -> "").collect(Collectors.joining()); + // } } protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { - // We may consider adding manually an initial '---' prefix to help management of multiple documents - // if (!input.trim().startsWith("---")) { - // input = "---" + "\n" + input; - // } - try { - // https://stackoverflow.com/questions/25222327/deserialize-pojos-from-multiple-yaml-documents-in-a-single-file-in-jackson - // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-375328648 - // 2023-01: For now, we get 'Cannot deserialize value of type `com.fasterxml.jackson.databind.node.ObjectNode` from Array value' - // JsonParser yamlParser = objectMapper.getFactory().createParser(input); - // List docs = objectMapper.readValues(yamlParser, ObjectNode.class).readAll(); - // return objectMapper.writeValueAsString(docs); - - // 2023-01: This returns JSON instead of YAML - // This will transit with a JsonNode - // A JsonNode may keep the comments from the input node - // JsonNode jsonNode = objectMapper.readTree(input); - //Not 'toPrettyString' as one could require no INDENT_OUTPUT - // return jsonNode.toPrettyString(); ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); String outputFromjackson = objectMapper.writeValueAsString(objectNode); @@ -141,4 +105,29 @@ protected String format(ObjectMapper objectMapper, String input) throws IllegalA throw new AssertionError("Unable to format. input='" + input + "'", e); } } + + protected static class SpotlessDefaultPrettyPrinter extends DefaultPrettyPrinter { + private static final long serialVersionUID = 1L; + private final boolean spaceBeforeSeparator; + + public SpotlessDefaultPrettyPrinter(boolean spaceBeforeSeparator) { + this.spaceBeforeSeparator = spaceBeforeSeparator; + } + + @Override + public DefaultPrettyPrinter createInstance() { + return new DefaultPrettyPrinter(this); + } + + @Override + public DefaultPrettyPrinter withSeparators(Separators separators) { + this._separators = separators; + if (spaceBeforeSeparator) { + this._objectFieldValueSeparatorWithSpaces = " " + separators.getObjectFieldValueSeparator() + " "; + } else { + this._objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSeparator() + " "; + } + return this; + } + } } diff --git a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java index 2fadf31d78..7690913f34 100644 --- a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java +++ b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java @@ -24,6 +24,7 @@ * A DTO holding the options for Jackson-based formatters */ public class JacksonConfig implements Serializable { + private static final long serialVersionUID = 1L; private static final Map DEFAULT_FEATURE_TOGGLES; From 5e1a0e97ed6d53f3694309e161460b459e9cb802 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Tue, 17 Jan 2023 12:53:20 +0400 Subject: [PATCH 04/18] Jackson - Yaml starts diverging to enable yanml-specific options --- .../glue/json/JacksonJsonFormatterFunc.java | 40 ++++----- .../glue/yaml/JacksonYamlFormatterFunc.java | 28 +++++-- .../diffplug/spotless/json/JacksonConfig.java | 11 +-- .../spotless/yaml/JacksonYamlConfig.java | 50 ++++++++++++ .../spotless/yaml/JacksonYamlStep.java | 2 +- .../gradle/spotless/JacksonGradleConfig.java | 67 +++++++++++++++ .../gradle/spotless/JsonExtension.java | 23 +++++- .../gradle/spotless/SpotlessExtension.java | 6 ++ .../gradle/spotless/YamlExtension.java | 75 +++++++++++++++++ .../gradle/spotless/YamlExtensionTest.java | 81 +++++++++++++++++++ plugin-maven/CHANGES.md | 7 +- plugin-maven/README.md | 28 +++++-- .../spotless/maven/yaml/JacksonYaml.java | 10 ++- .../spotless/maven/yaml/YamlTest.java | 8 +- ...ay_with_bracket.clean.no_start_marker.yaml | 11 +++ ...th_bracket.clean.spaceBeforeSeparator.yaml | 6 +- 16 files changed, 387 insertions(+), 66 deletions(-) create mode 100644 lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlConfig.java create mode 100644 plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java create mode 100644 plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java create mode 100644 plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java create mode 100644 testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.yaml diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java index c44ff0d0d1..934e60fcd8 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java @@ -18,6 +18,7 @@ import java.io.IOException; import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonFactoryBuilder; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.util.DefaultIndenter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; @@ -47,12 +48,22 @@ public String apply(String input) throws Exception { return format(objectMapper, input); } + protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { + try { + ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); + return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectNode); + } catch (JsonProcessingException e) { + throw new AssertionError("Unable to format. input='" + input + "'", e); + } + } + /** * @return a {@link JsonFactory}. May be overridden to handle alternative formats. * @see jackson-dataformats-text */ protected JsonFactory makeJsonFactory() { - return new JsonFactory(); + // We may later accept JsonFactory.Features + return new JsonFactoryBuilder().build(); } protected ObjectMapper makeObjectMapper() { @@ -76,7 +87,9 @@ protected ObjectMapper makeObjectMapper() { protected DefaultPrettyPrinter makePrinter() { boolean spaceBeforeSeparator = jacksonConfig.isSpaceBeforeSeparator(); - DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(getIndentation(), "\n"); + // DefaultIndenter default constructor relies on 2 whitespaces as default tabulation + // By we want to force '\n' as eol given Spotless provides LF-input (whatever the actual File content/current OS) + DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(" ", "\n"); DefaultPrettyPrinter printer = new SpotlessDefaultPrettyPrinter(spaceBeforeSeparator); printer.indentObjectsWith(indenter); @@ -84,28 +97,6 @@ protected DefaultPrettyPrinter makePrinter() { return printer; } - protected String getIndentation() { - // DefaultIndenter default constructor relies on this - return " "; - // int indentSpaces = jacksonConfig.getIndentSpaces(); - // if (indentSpaces < 0) { - // return "\t"; - // } else { - // return IntStream.range(0, indentSpaces).mapToObj(i -> "").collect(Collectors.joining()); - // } - } - - protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { - try { - ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); - String outputFromjackson = objectMapper.writeValueAsString(objectNode); - - return outputFromjackson; - } catch (JsonProcessingException e) { - throw new AssertionError("Unable to format. input='" + input + "'", e); - } - } - protected static class SpotlessDefaultPrettyPrinter extends DefaultPrettyPrinter { private static final long serialVersionUID = 1L; private final boolean spaceBeforeSeparator; @@ -123,6 +114,7 @@ public DefaultPrettyPrinter createInstance() { public DefaultPrettyPrinter withSeparators(Separators separators) { this._separators = separators; if (spaceBeforeSeparator) { + // This is Jackson default behavior this._objectFieldValueSeparatorWithSpaces = " " + separators.getObjectFieldValueSeparator() + " "; } else { this._objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSeparator() + " "; diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java index 6a471a884c..f7686ad503 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java @@ -17,23 +17,39 @@ import java.io.IOException; +import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactoryBuilder; +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import com.diffplug.spotless.glue.json.JacksonJsonFormatterFunc; -import com.diffplug.spotless.json.JacksonConfig; +import com.diffplug.spotless.yaml.JacksonYamlConfig; public class JacksonYamlFormatterFunc extends JacksonJsonFormatterFunc { + final JacksonYamlConfig yamlConfig; - public JacksonYamlFormatterFunc(JacksonConfig jacksonConfig) { + public JacksonYamlFormatterFunc(JacksonYamlConfig jacksonConfig) { super(jacksonConfig); + this.yamlConfig = jacksonConfig; } - @Override - protected YAMLFactory makeJsonFactory() { - return new YAMLFactory(); + protected JsonFactory makeJsonFactory() { + YAMLFactoryBuilder yamlFactoryBuilder = new YAMLFactoryBuilder(new YAMLFactory()); + + // Configure the ObjectMapper + // https://github.com/FasterXML/jackson-databind#commonly-used-features + yamlConfig.getYamlFeatureToToggle().forEach((rawFeature, toggle) -> { + // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection + // Refers to 'com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature' + YAMLGenerator.Feature feature = YAMLGenerator.Feature.valueOf(rawFeature); + + yamlFactoryBuilder.configure(feature, toggle); + }); + + return yamlFactoryBuilder.build(); } @Override @@ -56,7 +72,7 @@ protected String format(ObjectMapper objectMapper, String input) throws IllegalA //Not 'toPrettyString' as one could require no INDENT_OUTPUT // return jsonNode.toPrettyString(); ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); - String outputFromjackson = objectMapper.writeValueAsString(objectNode); + String outputFromjackson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectNode); return outputFromjackson; } catch (JsonProcessingException e) { diff --git a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java index 7690913f34..d5ca990b08 100644 --- a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java +++ b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java @@ -31,6 +31,7 @@ public class JacksonConfig implements Serializable { static { Map defaultFeatureToggles = new LinkedHashMap<>(); // We activate by default the PrettyPrinter from Jackson + // @see com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT defaultFeatureToggles.put("INDENT_OUTPUT", true); DEFAULT_FEATURE_TOGGLES = defaultFeatureToggles; } @@ -41,8 +42,6 @@ public class JacksonConfig implements Serializable { // By default, Jackson adds a ' ' before separator, which is not standard with most IDE/JSON libraries protected boolean spaceBeforeSeparator = false; - // protected int indentSpaces; - public Map getFeatureToToggle() { return Collections.unmodifiableMap(featureToToggle); } @@ -62,12 +61,4 @@ public boolean isSpaceBeforeSeparator() { public void setSpaceBeforeSeparator(boolean spaceBeforeSeparator) { this.spaceBeforeSeparator = spaceBeforeSeparator; } - - // public int getIndentSpaces() { - // return indentSpaces; - // } - - // public void setIndentSpaces(int indentSpaces) { - // this.indentSpaces = indentSpaces; - // } } diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlConfig.java b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlConfig.java new file mode 100644 index 0000000000..2463b9603f --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlConfig.java @@ -0,0 +1,50 @@ +/* + * Copyright 2023 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.yaml; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.diffplug.spotless.json.JacksonConfig; + +/** + * Specialization of {@link JacksonConfig} for YAML documents + */ +public class JacksonYamlConfig extends JacksonConfig { + private static final long serialVersionUID = 1L; + + protected Map yamlFeatureToToggle = new LinkedHashMap<>(); + + public Map getYamlFeatureToToggle() { + return Collections.unmodifiableMap(yamlFeatureToToggle); + } + + /** + * @see com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature + */ + public void setYamlFeatureToToggle(Map yamlFeatureToToggle) { + this.yamlFeatureToToggle = yamlFeatureToToggle; + } + + /** + * @see com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature + */ + public void appendYamlFeatureToToggle(Map features) { + this.yamlFeatureToToggle.putAll(features); + } + +} diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java index 944d90e6c9..04d1895fe0 100644 --- a/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java +++ b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java @@ -73,7 +73,7 @@ private State(JacksonConfig jacksonConfig, FormatterFunc toFormatter() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.yaml.JacksonYamlFormatterFunc"); - Constructor constructor = formatterFunc.getConstructor(JacksonConfig.class); + Constructor constructor = formatterFunc.getConstructor(JacksonYamlConfig.class); return (FormatterFunc) constructor.newInstance(jacksonConfig); } } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java new file mode 100644 index 0000000000..d388f45d11 --- /dev/null +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java @@ -0,0 +1,67 @@ +/* + * Copyright 2023 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.gradle.spotless; + +import java.util.Collections; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.json.JacksonConfig; +import com.diffplug.spotless.json.JacksonJsonStep; + +public abstract class JacksonGradleConfig { + protected final FormatExtension formatExtension; + + protected JacksonConfig jacksonConfig; + + protected String version = JacksonJsonStep.defaultVersion(); + + public JacksonGradleConfig(JacksonConfig jacksonConfig, FormatExtension formatExtension) { + this.formatExtension = formatExtension; + + this.jacksonConfig = jacksonConfig; + formatExtension.addStep(createStep()); + } + + public JacksonGradleConfig(FormatExtension formatExtension) { + this(new JacksonConfig(), formatExtension); + } + + public JacksonGradleConfig config(JacksonConfig jacksonConfig) { + this.jacksonConfig = jacksonConfig; + formatExtension.replaceStep(createStep()); + return this; + } + + public JacksonGradleConfig feature(String feature, boolean toggle) { + this.jacksonConfig.appendFeatureToToggle(Collections.singletonMap(feature, toggle)); + formatExtension.replaceStep(createStep()); + return this; + } + + public JacksonGradleConfig spaceBeforeSeparator(boolean toggle) { + this.jacksonConfig.setSpaceBeforeSeparator(toggle); + formatExtension.replaceStep(createStep()); + return this; + } + + public JacksonGradleConfig version(String version) { + this.version = version; + formatExtension.replaceStep(createStep()); + return this; + } + + protected abstract FormatterStep createStep(); +} diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java index 25182fa4bc..542b2d5431 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 DiffPlug + * Copyright 2016-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,8 @@ import javax.inject.Inject; import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.json.JacksonConfig; +import com.diffplug.spotless.json.JacksonJsonStep; import com.diffplug.spotless.json.JsonSimpleStep; import com.diffplug.spotless.json.gson.GsonStep; @@ -47,6 +49,10 @@ public GsonConfig gson() { return new GsonConfig(); } + public JacksonJsonGradleConfig jackson() { + return new JacksonJsonGradleConfig(this); + } + public class SimpleConfig { private int indent; @@ -108,4 +114,19 @@ private FormatterStep createStep() { } } + public static class JacksonJsonGradleConfig extends JacksonGradleConfig { + + public JacksonJsonGradleConfig(JacksonConfig jacksonConfig, FormatExtension formatExtension) { + super(jacksonConfig, formatExtension); + } + + public JacksonJsonGradleConfig(FormatExtension formatExtension) { + this(new JacksonConfig(), formatExtension); + } + + @Override + protected FormatterStep createStep() { + return JacksonJsonStep.create(jacksonConfig, version, formatExtension.provisioner()); + } + } } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java index 1c65fad310..8c3128e02d 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java @@ -193,6 +193,12 @@ public void json(Action closure) { format(JsonExtension.NAME, JsonExtension.class, closure); } + /** Configures the special YAML-specific extension. */ + public void yaml(Action closure) { + requireNonNull(closure); + format(JsonExtension.NAME, YamlExtension.class, closure); + } + /** Configures a custom extension. */ public void format(String name, Action closure) { requireNonNull(name, "name"); diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java new file mode 100644 index 0000000000..5907ea985a --- /dev/null +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java @@ -0,0 +1,75 @@ +/* + * Copyright 2016-2023 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.gradle.spotless; + +import java.util.Collections; + +import javax.inject.Inject; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.json.JacksonJsonStep; +import com.diffplug.spotless.yaml.JacksonYamlConfig; +import com.diffplug.spotless.yaml.JacksonYamlStep; + +public class YamlExtension extends FormatExtension { + private static final String DEFAULT_GSON_VERSION = JacksonJsonStep.defaultVersion(); + static final String NAME = "yaml"; + + @Inject + public YamlExtension(SpotlessExtension spotless) { + super(spotless); + } + + @Override + protected void setupTask(SpotlessTask task) { + if (target == null) { + throw noDefaultTargetException(); + } + super.setupTask(task); + } + + public JacksonGradleConfig jackson() { + return new JacksonYamlGradleConfig(this); + } + + public class JacksonYamlGradleConfig extends JacksonGradleConfig { + protected JacksonYamlConfig jacksonConfig; + + public JacksonYamlGradleConfig(JacksonYamlConfig jacksonConfig, FormatExtension formatExtension) { + super(jacksonConfig, formatExtension); + + this.jacksonConfig = jacksonConfig; + } + + public JacksonYamlGradleConfig(FormatExtension formatExtension) { + this(new JacksonYamlConfig(), formatExtension); + } + + /** + * @see com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature + */ + public JacksonGradleConfig yamlFeature(String feature, boolean toggle) { + this.jacksonConfig.appendYamlFeatureToToggle(Collections.singletonMap(feature, toggle)); + formatExtension.replaceStep(createStep()); + return this; + } + + @Override + protected FormatterStep createStep() { + return JacksonYamlStep.create(jacksonConfig, version, provisioner()); + } + } +} diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java new file mode 100644 index 0000000000..c16053a661 --- /dev/null +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021-2023 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.gradle.spotless; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +class YamlExtensionTest extends GradleIntegrationHarness { + @Test + void testFormatYaml_WithJackson_defaultConfig_separatorComments() throws IOException { + setFile("build.gradle").toLines( + "plugins {", + " id 'java'", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "spotless {", + " yaml {", + " target 'src/**/*.yaml'", + " jackson()", + "}", + "}"); + setFile("src/main/resources/example.yaml").toResource("yaml/separator_comments.yaml"); + gradleRunner().withArguments("spotlessApply").build(); + assertFile("src/main/resources/example.yaml").sameAsResource("yaml/separator_comments.clean.yaml"); + } + + @Test + void testFormatYaml_WithJackson_defaultConfig_arrayBrackets_spaceBeforeSeparator() throws IOException { + setFile("build.gradle").toLines( + "plugins {", + " id 'java'", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "spotless {", + " yaml {", + " target 'src/**/*.yaml'", + " jackson().spaceBeforeSeparator(true)", + "}", + "}"); + setFile("src/main/resources/example.yaml").toResource("yaml/array_with_bracket.yaml"); + gradleRunner().withArguments("spotlessApply").build(); + assertFile("src/main/resources/example.yaml").sameAsResource("yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml"); + } + + // see YAMLGenerator.Feature.WRITE_DOC_START_MARKER + @Test + void testFormatYaml_WithJackson_skipDocStartMarker() throws IOException { + setFile("build.gradle").toLines( + "plugins {", + " id 'java'", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "spotless {", + " yaml {", + " target 'src/**/*.yaml'", + " jackson().yamlFeature('WRITE_DOC_START_MARKER', false)", + "}", + "}"); + setFile("src/main/resources/example.yaml").toResource("yaml/array_with_bracket.yaml"); + gradleRunner().withArguments("spotlessApply").build(); + assertFile("src/main/resources/example.yaml").sameAsResource("yaml/array_with_bracket.clean.no_start_marker.yaml"); + } + +} diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index d6326cba12..5bcc4b24c6 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -3,13 +3,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] -### Added -* Introduce `` ([#1492](https://github.com/diffplug/spotless/pull/1492)) - * **POTENTIALLY BREAKING** `JacksonYaml` is now configured with a `Map` to configure features -* Jackson (JSON and YAML) has new `spaceBeforeSeparator` option - * **POTENTIALLY BREAKING** `spaceBeforeSeparator` is defaulted to false while the formatter was behaving with `true` -## [2.30.0] - 2023-01-13 +# [2.30.0] - 2023-01-13 ### Added * Add option `editorConfigFile` for `ktLint` [#142](https://github.com/diffplug/spotless/issues/142) * **POTENTIALLY BREAKING** `ktlint` step now modifies license headers. Make sure to put `licenseHeader` *after* `ktlint`. diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 6dca992591..e76d424611 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -12,8 +12,8 @@ output = [ ].join('\n'); --> [![Maven central](https://img.shields.io/badge/mavencentral-com.diffplug.spotless%3Aspotless--maven--plugin-blue.svg)](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.diffplug.spotless%22%20AND%20a%3A%22spotless-maven-plugin%22) -[![Javadoc](https://img.shields.io/badge/javadoc-yes-blue.svg)](https://javadoc.io/doc/com.diffplug.spotless/spotless-maven-plugin/2.30.0/index.html) -[![Changelog](https://img.shields.io/badge/changelog-2.30.0-brightgreen.svg)](CHANGES.md) +[![Javadoc](https://img.shields.io/badge/javadoc-yes-blue.svg)](https://javadoc.io/doc/com.diffplug.spotless/spotless-maven-plugin/2.29.0/index.html) +[![Changelog](https://img.shields.io/badge/changelog-2.29.0-brightgreen.svg)](CHANGES.md) [![Circle CI](https://circleci.com/gh/diffplug/spotless/tree/main.svg?style=shield)](https://circleci.com/gh/diffplug/spotless/tree/main) [![Live chat](https://img.shields.io/badge/gitter-chat-brightgreen.svg)](https://gitter.im/diffplug/spotless) @@ -864,6 +864,7 @@ For details, see the [npm detection](#npm-detection) and [`.npmrc` detection](#n + ``` @@ -898,6 +899,22 @@ all HTML characters are written escaped or none. Set `escapeHtml` if you prefer [javadoc of String](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#compareTo(java.lang.String)) for details. +### Jackson + +Uses Jackson for formatting. + +```xml + + 2.14.1 + + true + false + true|false + + false + +``` + @@ -924,10 +941,11 @@ Uses Jackson and YAMLFactory to pretty print objects: ```xml 2.14.1 - - true + + true false - true|false + false + true|false false diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java index 1cd23bc3cc..9741c3f5d0 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java @@ -21,10 +21,10 @@ import org.apache.maven.plugins.annotations.Parameter; import com.diffplug.spotless.FormatterStep; -import com.diffplug.spotless.json.JacksonConfig; import com.diffplug.spotless.maven.FormatterFactory; import com.diffplug.spotless.maven.FormatterStepConfig; import com.diffplug.spotless.maven.FormatterStepFactory; +import com.diffplug.spotless.yaml.JacksonYamlConfig; import com.diffplug.spotless.yaml.JacksonYamlStep; /** @@ -36,16 +36,20 @@ public class JacksonYaml implements FormatterStepFactory { private String version = JacksonYamlStep.defaultVersion(); @Parameter - private boolean spaceBeforeSeparator = new JacksonConfig().isSpaceBeforeSeparator(); + private boolean spaceBeforeSeparator = new JacksonYamlConfig().isSpaceBeforeSeparator(); @Parameter private Map features = Collections.emptyMap(); + @Parameter + private Map yamlFeatures = Collections.emptyMap(); + @Override public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { - JacksonConfig jacksonConfig = new JacksonConfig(); + JacksonYamlConfig jacksonConfig = new JacksonYamlConfig(); jacksonConfig.appendFeatureToToggle(features); + jacksonConfig.appendYamlFeatureToToggle(yamlFeatures); jacksonConfig.setSpaceBeforeSeparator(spaceBeforeSeparator); return JacksonYamlStep diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java index 51f8da99f4..aaea2c65b1 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java @@ -15,14 +15,11 @@ */ package com.diffplug.spotless.maven.yaml; -import static org.assertj.core.api.Assertions.assertThat; - import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.diffplug.spotless.maven.MavenIntegrationHarness; -import com.diffplug.spotless.maven.MavenRunner.Result; public class YamlTest extends MavenIntegrationHarness { private static final Logger LOGGER = LoggerFactory.getLogger(YamlTest.class); @@ -32,10 +29,7 @@ public void testFormatYaml_WithJackson_defaultConfig_separatorComments() throws writePomWithYamlSteps(""); setFile("yaml_test.yaml").toResource("yaml/separator_comments.yaml"); - Result runNoError = mavenRunner().withArguments("spotless:apply").runNoError(); - LOGGER.error("result: {}", runNoError); - assertThat(runNoError.exitValue()).as("Run without error %s", runNoError).isEqualTo(0); - LOGGER.error("GOGO"); + mavenRunner().withArguments("spotless:apply").runNoError(); assertFile("yaml_test.yaml").sameAsResource("yaml/separator_comments.clean.yaml"); } diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.yaml new file mode 100644 index 0000000000..7f2f5a96cd --- /dev/null +++ b/testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.yaml @@ -0,0 +1,11 @@ +episodes: +- 1 +- 2 +- 3 +- 4 +- 5 +- 6 +- 7 +best-jedi: + name: "Obi-Wan" + side: "light" diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml index c6f891b9de..7dc9255e06 100644 --- a/testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml +++ b/testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml @@ -7,6 +7,6 @@ episodes: - 5 - 6 - 7 -best-jedi: - name: "Obi-Wan" - side: "light" \ No newline at end of file +best-jedi : + name : "Obi-Wan" + side : "light" From 533dc9999c56ca8dbd381f3ea74b79bcd5774e50 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 00:33:53 +0400 Subject: [PATCH 05/18] Progress with gradle and tests --- .../glue/json/AJacksonFormatterFunc.java | 87 +++++++++++++++++++ .../glue/json/JacksonJsonFormatterFunc.java | 59 ++++--------- .../glue/yaml/JacksonYamlFormatterFunc.java | 9 +- .../diffplug/spotless/json/JacksonConfig.java | 14 +-- .../spotless/json/JacksonJsonConfig.java | 59 +++++++++++++ .../spotless/json/JacksonJsonStep.java | 6 +- .../spotless/yaml/JacksonYamlStep.java | 13 +-- .../gradle/spotless/JacksonGradleConfig.java | 6 -- .../gradle/spotless/JsonExtension.java | 28 +++++- .../gradle/spotless/YamlExtension.java | 6 +- .../gradle/spotless/JsonExtensionTest.java | 56 ++++++++---- .../gradle/spotless/YamlExtensionTest.java | 33 ++----- .../spotless/maven/json/JacksonJson.java | 6 +- .../spotless/maven/yaml/JacksonYaml.java | 4 - ...ay_with_bracket.clean.no_start_marker.yaml | 4 +- 15 files changed, 259 insertions(+), 131 deletions(-) create mode 100644 lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java create mode 100644 lib/src/main/java/com/diffplug/spotless/json/JacksonJsonConfig.java diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java new file mode 100644 index 0000000000..a835c85f9a --- /dev/null +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java @@ -0,0 +1,87 @@ +/* + * Copyright 2021-2023 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.glue.json; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.json.JacksonConfig; + +/** + * A {@link FormatterFunc} based on Jackson library + */ +// https://github.com/FasterXML/jackson-dataformats-text/issues/372 +public abstract class AJacksonFormatterFunc implements FormatterFunc { + private JacksonConfig jacksonConfig; + + public AJacksonFormatterFunc(JacksonConfig jacksonConfig) { + this.jacksonConfig = jacksonConfig; + } + + @Override + public String apply(String input) throws Exception { + ObjectMapper objectMapper = makeObjectMapper(); + + return format(objectMapper, input); + } + + protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { + try { + ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); + return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectNode); + } catch (JsonProcessingException e) { + throw new AssertionError("Unable to format. input='" + input + "'", e); + } + } + + /** + * @return a {@link JsonFactory}. May be overridden to handle alternative formats. + * @see jackson-dataformats-text + */ + protected abstract JsonFactory makeJsonFactory(); + + protected ObjectMapper makeObjectMapper() { + JsonFactory jsonFactory = makeJsonFactory(); + ObjectMapper objectMapper = new ObjectMapper(jsonFactory); + + objectMapper.setDefaultPrettyPrinter(makePrinter()); + + // Configure the ObjectMapper + // https://github.com/FasterXML/jackson-databind#commonly-used-features + jacksonConfig.getFeatureToToggle().forEach((rawFeature, toggle) -> { + // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection + SerializationFeature feature = SerializationFeature.valueOf(rawFeature); + + objectMapper.configure(feature, toggle); + }); + + new JsonFactory().configure(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, true); + + return objectMapper; + } + + protected DefaultPrettyPrinter makePrinter() { + return new DefaultPrettyPrinter(); + } +} diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java index 934e60fcd8..5aadcc568f 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java @@ -15,99 +15,72 @@ */ package com.diffplug.spotless.glue.json; -import java.io.IOException; - import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonFactoryBuilder; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.util.DefaultIndenter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.core.util.Separators; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.diffplug.spotless.FormatterFunc; -import com.diffplug.spotless.json.JacksonConfig; +import com.diffplug.spotless.json.JacksonJsonConfig; /** * A {@link FormatterFunc} based on Jackson library */ // https://github.com/FasterXML/jackson-dataformats-text/issues/372 -public class JacksonJsonFormatterFunc implements FormatterFunc { - private JacksonConfig jacksonConfig; +public class JacksonJsonFormatterFunc extends AJacksonFormatterFunc { + private JacksonJsonConfig jacksonConfig; - public JacksonJsonFormatterFunc(JacksonConfig jacksonConfig) { + public JacksonJsonFormatterFunc(JacksonJsonConfig jacksonConfig) { + super(jacksonConfig); this.jacksonConfig = jacksonConfig; } - @Override - public String apply(String input) throws Exception { - ObjectMapper objectMapper = makeObjectMapper(); - - return format(objectMapper, input); - } - - protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { - try { - ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); - return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectNode); - } catch (JsonProcessingException e) { - throw new AssertionError("Unable to format. input='" + input + "'", e); - } - } - /** * @return a {@link JsonFactory}. May be overridden to handle alternative formats. * @see jackson-dataformats-text */ protected JsonFactory makeJsonFactory() { - // We may later accept JsonFactory.Features - return new JsonFactoryBuilder().build(); - } - - protected ObjectMapper makeObjectMapper() { - JsonFactory jsonFactory = makeJsonFactory(); - ObjectMapper objectMapper = new ObjectMapper(jsonFactory); - - objectMapper.setDefaultPrettyPrinter(makePrinter()); + JsonFactory jsonFactory = new JsonFactoryBuilder().build(); // Configure the ObjectMapper // https://github.com/FasterXML/jackson-databind#commonly-used-features - jacksonConfig.getFeatureToToggle().forEach((rawFeature, toggle) -> { + jacksonConfig.getJsonFeatureToToggle().forEach((rawFeature, toggle) -> { // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection - SerializationFeature feature = SerializationFeature.valueOf(rawFeature); + JsonGenerator.Feature feature = JsonGenerator.Feature.valueOf(rawFeature); - objectMapper.configure(feature, toggle); + jsonFactory.configure(feature, toggle); }); - return objectMapper; + return jsonFactory; } + @Override protected DefaultPrettyPrinter makePrinter() { boolean spaceBeforeSeparator = jacksonConfig.isSpaceBeforeSeparator(); // DefaultIndenter default constructor relies on 2 whitespaces as default tabulation // By we want to force '\n' as eol given Spotless provides LF-input (whatever the actual File content/current OS) DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(" ", "\n"); - DefaultPrettyPrinter printer = new SpotlessDefaultPrettyPrinter(spaceBeforeSeparator); + DefaultPrettyPrinter printer = new SpotlessJsonPrettyPrinter(spaceBeforeSeparator); printer.indentObjectsWith(indenter); printer.indentArraysWith(indenter); return printer; } - protected static class SpotlessDefaultPrettyPrinter extends DefaultPrettyPrinter { + protected static class SpotlessJsonPrettyPrinter extends DefaultPrettyPrinter { private static final long serialVersionUID = 1L; private final boolean spaceBeforeSeparator; - public SpotlessDefaultPrettyPrinter(boolean spaceBeforeSeparator) { + public SpotlessJsonPrettyPrinter(boolean spaceBeforeSeparator) { this.spaceBeforeSeparator = spaceBeforeSeparator; } @Override public DefaultPrettyPrinter createInstance() { - return new DefaultPrettyPrinter(this); + return new SpotlessJsonPrettyPrinter(spaceBeforeSeparator); } @Override diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java index f7686ad503..3986374c9e 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java @@ -25,15 +25,19 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactoryBuilder; import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; -import com.diffplug.spotless.glue.json.JacksonJsonFormatterFunc; +import com.diffplug.spotless.glue.json.AJacksonFormatterFunc; import com.diffplug.spotless.yaml.JacksonYamlConfig; -public class JacksonYamlFormatterFunc extends JacksonJsonFormatterFunc { +public class JacksonYamlFormatterFunc extends AJacksonFormatterFunc { final JacksonYamlConfig yamlConfig; public JacksonYamlFormatterFunc(JacksonYamlConfig jacksonConfig) { super(jacksonConfig); this.yamlConfig = jacksonConfig; + + if (jacksonConfig == null) { + throw new IllegalArgumentException("ARG"); + } } protected JsonFactory makeJsonFactory() { @@ -43,7 +47,6 @@ protected JsonFactory makeJsonFactory() { // https://github.com/FasterXML/jackson-databind#commonly-used-features yamlConfig.getYamlFeatureToToggle().forEach((rawFeature, toggle) -> { // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection - // Refers to 'com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature' YAMLGenerator.Feature feature = YAMLGenerator.Feature.valueOf(rawFeature); yamlFactoryBuilder.configure(feature, toggle); diff --git a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java index d5ca990b08..250b77d1f1 100644 --- a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java +++ b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java @@ -21,7 +21,7 @@ import java.util.Map; /** - * A DTO holding the options for Jackson-based formatters + * A DTO holding the basic for Jackson-based formatters */ public class JacksonConfig implements Serializable { private static final long serialVersionUID = 1L; @@ -38,10 +38,6 @@ public class JacksonConfig implements Serializable { protected Map featureToToggle = new LinkedHashMap<>(); - // https://github.com/revelc/formatter-maven-plugin/pull/280 - // By default, Jackson adds a ' ' before separator, which is not standard with most IDE/JSON libraries - protected boolean spaceBeforeSeparator = false; - public Map getFeatureToToggle() { return Collections.unmodifiableMap(featureToToggle); } @@ -53,12 +49,4 @@ public void setFeatureToToggle(Map featureToToggle) { public void appendFeatureToToggle(Map features) { this.featureToToggle.putAll(features); } - - public boolean isSpaceBeforeSeparator() { - return spaceBeforeSeparator; - } - - public void setSpaceBeforeSeparator(boolean spaceBeforeSeparator) { - this.spaceBeforeSeparator = spaceBeforeSeparator; - } } diff --git a/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonConfig.java b/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonConfig.java new file mode 100644 index 0000000000..50b28605d1 --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonConfig.java @@ -0,0 +1,59 @@ +/* + * Copyright 2023 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; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Specialization of {@link JacksonConfig} for JSON documents + */ +public class JacksonJsonConfig extends JacksonConfig { + private static final long serialVersionUID = 1L; + + protected Map jsonFeatureToToggle = new LinkedHashMap<>(); + + // https://github.com/revelc/formatter-maven-plugin/pull/280 + // By default, Jackson adds a ' ' before separator, which is not standard with most IDE/JSON libraries + protected boolean spaceBeforeSeparator = false; + + public Map getJsonFeatureToToggle() { + return Collections.unmodifiableMap(jsonFeatureToToggle); + } + + /** + * @see com.fasterxml.jackson.core.JsonGenerator.Feature + */ + public void setJsonFeatureToToggle(Map jsonFeatureToToggle) { + this.jsonFeatureToToggle = jsonFeatureToToggle; + } + + /** + * @see com.fasterxml.jackson.core.JsonGenerator.Feature + */ + public void appendJsonFeatureToToggle(Map features) { + this.jsonFeatureToToggle.putAll(features); + } + + public boolean isSpaceBeforeSeparator() { + return spaceBeforeSeparator; + } + + public void setSpaceBeforeSeparator(boolean spaceBeforeSeparator) { + this.spaceBeforeSeparator = spaceBeforeSeparator; + } +} diff --git a/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonStep.java b/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonStep.java index 0fe1ab057b..f15edbbd42 100644 --- a/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonStep.java +++ b/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonStep.java @@ -41,7 +41,7 @@ public static String defaultVersion() { return DEFAULT_VERSION; } - public static FormatterStep create(JacksonConfig jacksonConfig, + public static FormatterStep create(JacksonJsonConfig jacksonConfig, String jacksonVersion, Provisioner provisioner) { Objects.requireNonNull(provisioner, "provisioner cannot be null"); @@ -51,7 +51,7 @@ public static FormatterStep create(JacksonConfig jacksonConfig, } public static FormatterStep create(Provisioner provisioner) { - return create(new JacksonConfig(), defaultVersion(), provisioner); + return create(new JacksonJsonConfig(), defaultVersion(), provisioner); } private static final class State implements Serializable { @@ -72,7 +72,7 @@ private State(JacksonConfig jacksonConfig, FormatterFunc toFormatter() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class formatterFunc = jarState.getClassLoader().loadClass("com.diffplug.spotless.glue.json.JacksonJsonFormatterFunc"); - Constructor constructor = formatterFunc.getConstructor(JacksonConfig.class); + Constructor constructor = formatterFunc.getConstructor(JacksonJsonConfig.class); return (FormatterFunc) constructor.newInstance(jacksonConfig); } } diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java index 04d1895fe0..201199fe8b 100644 --- a/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java +++ b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java @@ -25,7 +25,6 @@ import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.JarState; import com.diffplug.spotless.Provisioner; -import com.diffplug.spotless.json.JacksonConfig; /** * Simple YAML formatter which reformats the file according to Jackson YAMLFactory. @@ -42,7 +41,7 @@ public static String defaultVersion() { return DEFAULT_VERSION; } - public static FormatterStep create(JacksonConfig jacksonConfig, + public static FormatterStep create(JacksonYamlConfig jacksonConfig, String jacksonVersion, Provisioner provisioner) { Objects.requireNonNull(provisioner, "provisioner cannot be null"); @@ -52,21 +51,25 @@ public static FormatterStep create(JacksonConfig jacksonConfig, } public static FormatterStep create(Provisioner provisioner) { - return create(new JacksonConfig(), defaultVersion(), provisioner); + return create(new JacksonYamlConfig(), defaultVersion(), provisioner); } private static final class State implements Serializable { private static final long serialVersionUID = 1L; - private final JacksonConfig jacksonConfig; + private final JacksonYamlConfig jacksonConfig; private final JarState jarState; - private State(JacksonConfig jacksonConfig, + private State(JacksonYamlConfig jacksonConfig, String jacksonVersion, Provisioner provisioner) throws IOException { this.jacksonConfig = jacksonConfig; + if (jacksonConfig == null) { + throw new IllegalArgumentException("ARG"); + } + this.jarState = JarState.from(JacksonYamlStep.MAVEN_COORDINATE + jacksonVersion, provisioner); } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java index d388f45d11..afc0c36371 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java @@ -51,12 +51,6 @@ public JacksonGradleConfig feature(String feature, boolean toggle) { return this; } - public JacksonGradleConfig spaceBeforeSeparator(boolean toggle) { - this.jacksonConfig.setSpaceBeforeSeparator(toggle); - formatExtension.replaceStep(createStep()); - return this; - } - public JacksonGradleConfig version(String version) { this.version = version; formatExtension.replaceStep(createStep()); diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java index 542b2d5431..31f605809c 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java @@ -15,10 +15,12 @@ */ package com.diffplug.gradle.spotless; +import java.util.Collections; + import javax.inject.Inject; import com.diffplug.spotless.FormatterStep; -import com.diffplug.spotless.json.JacksonConfig; +import com.diffplug.spotless.json.JacksonJsonConfig; import com.diffplug.spotless.json.JacksonJsonStep; import com.diffplug.spotless.json.JsonSimpleStep; import com.diffplug.spotless.json.gson.GsonStep; @@ -49,7 +51,7 @@ public GsonConfig gson() { return new GsonConfig(); } - public JacksonJsonGradleConfig jackson() { + public JacksonJsonGradleConfig jacksonJson() { return new JacksonJsonGradleConfig(this); } @@ -115,17 +117,35 @@ private FormatterStep createStep() { } public static class JacksonJsonGradleConfig extends JacksonGradleConfig { + protected JacksonJsonConfig jacksonConfig; - public JacksonJsonGradleConfig(JacksonConfig jacksonConfig, FormatExtension formatExtension) { + public JacksonJsonGradleConfig(JacksonJsonConfig jacksonConfig, FormatExtension formatExtension) { super(jacksonConfig, formatExtension); + this.jacksonConfig = jacksonConfig; + + if (jacksonConfig == null) { + throw new IllegalArgumentException("ARG2"); + } } public JacksonJsonGradleConfig(FormatExtension formatExtension) { - this(new JacksonConfig(), formatExtension); + this(new JacksonJsonConfig(), formatExtension); + } + + /** + * @see com.fasterxml.jackson.core.JsonGenerator.Feature + */ + public JacksonGradleConfig jsonFeature(String feature, boolean toggle) { + this.jacksonConfig.appendJsonFeatureToToggle(Collections.singletonMap(feature, toggle)); + formatExtension.replaceStep(createStep()); + return this; } @Override protected FormatterStep createStep() { + if (jacksonConfig == null) { + throw new IllegalArgumentException("ARG3"); + } return JacksonJsonStep.create(jacksonConfig, version, formatExtension.provisioner()); } } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java index 5907ea985a..3fc12e0495 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java @@ -41,7 +41,7 @@ protected void setupTask(SpotlessTask task) { super.setupTask(task); } - public JacksonGradleConfig jackson() { + public JacksonGradleConfig jacksonYaml() { return new JacksonYamlGradleConfig(this); } @@ -52,6 +52,10 @@ public JacksonYamlGradleConfig(JacksonYamlConfig jacksonConfig, FormatExtension super(jacksonConfig, formatExtension); this.jacksonConfig = jacksonConfig; + + if (jacksonConfig == null) { + throw new IllegalArgumentException("ARG"); + } } public JacksonYamlGradleConfig(FormatExtension formatExtension) { diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JsonExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JsonExtensionTest.java index e2fb9f70aa..945c72cf75 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JsonExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JsonExtensionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2021-2022 DiffPlug + * Copyright 2021-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,9 +30,9 @@ void simpleDefaultFormatting() throws IOException { "repositories { mavenCentral() }", "spotless {", " json {", - " target 'examples/**/*.json'", - " simple()", - "}", + " target 'examples/**/*.json'", + " simple()", + " }", "}"); setFile("src/main/resources/example.json").toResource("json/nestedObjectBefore.json"); setFile("examples/main/resources/example.json").toResource("json/nestedObjectBefore.json"); @@ -51,9 +51,9 @@ void simpleFormattingWithCustomNumberOfSpaces() throws IOException { "repositories { mavenCentral() }", "spotless {", " json {", - " target 'src/**/*.json'", - " simple().indentWithSpaces(6)", - "}", + " target 'src/**/*.json'", + " simple().indentWithSpaces(6)", + " }", "}"); setFile("src/main/resources/example.json").toResource("json/singletonArrayBefore.json"); gradleRunner().withArguments("spotlessApply").build(); @@ -70,9 +70,9 @@ void gsonDefaultFormatting() throws IOException { "repositories { mavenCentral() }", "spotless {", " json {", - " target 'examples/**/*.json'", - " gson()", - "}", + " target 'examples/**/*.json'", + " gson()", + " }", "}"); setFile("src/main/resources/example.json").toResource("json/nestedObjectBefore.json"); setFile("examples/main/resources/example.json").toResource("json/nestedObjectBefore.json"); @@ -91,9 +91,9 @@ void gsonFormattingWithCustomNumberOfSpaces() throws IOException { "repositories { mavenCentral() }", "spotless {", " json {", - " target 'src/**/*.json'", - " gson().indentWithSpaces(6)", - "}", + " target 'src/**/*.json'", + " gson().indentWithSpaces(6)", + " }", "}"); setFile("src/main/resources/example.json").toResource("json/singletonArrayBefore.json"); gradleRunner().withArguments("spotlessApply").build(); @@ -110,9 +110,9 @@ void gsonFormattingWithSortingByKeys() throws IOException { "repositories { mavenCentral() }", "spotless {", " json {", - " target 'src/**/*.json'", - " gson().sortByKeys()", - "}", + " target 'src/**/*.json'", + " gson().sortByKeys()", + " }", "}"); setFile("src/main/resources/example.json").toResource("json/sortByKeysBefore.json"); gradleRunner().withArguments("spotlessApply").build(); @@ -129,13 +129,31 @@ void gsonFormattingWithHtmlEscape() throws IOException { "repositories { mavenCentral() }", "spotless {", " json {", - " target 'src/**/*.json'", - " gson().escapeHtml()", - "}", + " target 'src/**/*.json'", + " gson().escapeHtml()", + " }", "}"); setFile("src/main/resources/example.json").toResource("json/escapeHtmlGsonBefore.json"); gradleRunner().withArguments("spotlessApply").build(); assertFile("src/main/resources/example.json").sameAsResource("json/escapeHtmlGsonAfter.json"); } + @Test + void jacksonFormattingWithSortingByKeys() throws IOException { + setFile("build.gradle").toLines( + "plugins {", + " id 'java'", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "spotless {", + " json {", + " target 'src/**/*.json'", + " jacksonJson().feature('ORDER_MAP_ENTRIES_BY_KEYS', true)", + " }", + "}"); + setFile("src/main/resources/example.json").toResource("json/sortByKeysBefore.json"); + gradleRunner().withArguments("spotlessApply").build(); + assertFile("src/main/resources/example.json").sameAsResource("json/sortByKeysAfter_Jackson.json"); + } } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java index c16053a661..79e0df0d8d 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java @@ -30,34 +30,15 @@ void testFormatYaml_WithJackson_defaultConfig_separatorComments() throws IOExcep "repositories { mavenCentral() }", "spotless {", " yaml {", - " target 'src/**/*.yaml'", - " jackson()", - "}", + " target 'src/**/*.yaml'", + " jacksonYaml()", + " }", "}"); setFile("src/main/resources/example.yaml").toResource("yaml/separator_comments.yaml"); gradleRunner().withArguments("spotlessApply").build(); assertFile("src/main/resources/example.yaml").sameAsResource("yaml/separator_comments.clean.yaml"); } - @Test - void testFormatYaml_WithJackson_defaultConfig_arrayBrackets_spaceBeforeSeparator() throws IOException { - setFile("build.gradle").toLines( - "plugins {", - " id 'java'", - " id 'com.diffplug.spotless'", - "}", - "repositories { mavenCentral() }", - "spotless {", - " yaml {", - " target 'src/**/*.yaml'", - " jackson().spaceBeforeSeparator(true)", - "}", - "}"); - setFile("src/main/resources/example.yaml").toResource("yaml/array_with_bracket.yaml"); - gradleRunner().withArguments("spotlessApply").build(); - assertFile("src/main/resources/example.yaml").sameAsResource("yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml"); - } - // see YAMLGenerator.Feature.WRITE_DOC_START_MARKER @Test void testFormatYaml_WithJackson_skipDocStartMarker() throws IOException { @@ -69,9 +50,11 @@ void testFormatYaml_WithJackson_skipDocStartMarker() throws IOException { "repositories { mavenCentral() }", "spotless {", " yaml {", - " target 'src/**/*.yaml'", - " jackson().yamlFeature('WRITE_DOC_START_MARKER', false)", - "}", + " target 'src/**/*.yaml'", + " jacksonYaml()" + + " .yamlFeature('WRITE_DOC_START_MARKER', false)" + + " .yamlFeature('MINIMIZE_QUOTES', true)", + " }", "}"); setFile("src/main/resources/example.yaml").toResource("yaml/array_with_bracket.yaml"); gradleRunner().withArguments("spotlessApply").build(); diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java index 31c59a5f81..9bca852754 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java @@ -21,7 +21,7 @@ import org.apache.maven.plugins.annotations.Parameter; import com.diffplug.spotless.FormatterStep; -import com.diffplug.spotless.json.JacksonConfig; +import com.diffplug.spotless.json.JacksonJsonConfig; import com.diffplug.spotless.json.JacksonJsonStep; import com.diffplug.spotless.maven.FormatterFactory; import com.diffplug.spotless.maven.FormatterStepConfig; @@ -36,14 +36,14 @@ public class JacksonJson implements FormatterStepFactory { private String version = JacksonJsonStep.defaultVersion(); @Parameter - private boolean spaceBeforeSeparator = new JacksonConfig().isSpaceBeforeSeparator(); + private boolean spaceBeforeSeparator = new JacksonJsonConfig().isSpaceBeforeSeparator(); @Parameter private Map features = Collections.emptyMap(); @Override public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { - JacksonConfig jacksonConfig = new JacksonConfig(); + JacksonJsonConfig jacksonConfig = new JacksonJsonConfig(); jacksonConfig.appendFeatureToToggle(features); jacksonConfig.setSpaceBeforeSeparator(spaceBeforeSeparator); diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java index 9741c3f5d0..d97cc41647 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java @@ -35,9 +35,6 @@ public class JacksonYaml implements FormatterStepFactory { @Parameter private String version = JacksonYamlStep.defaultVersion(); - @Parameter - private boolean spaceBeforeSeparator = new JacksonYamlConfig().isSpaceBeforeSeparator(); - @Parameter private Map features = Collections.emptyMap(); @@ -50,7 +47,6 @@ public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { jacksonConfig.appendFeatureToToggle(features); jacksonConfig.appendYamlFeatureToToggle(yamlFeatures); - jacksonConfig.setSpaceBeforeSeparator(spaceBeforeSeparator); return JacksonYamlStep .create(jacksonConfig, version, stepConfig.getProvisioner()); diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.yaml index 7f2f5a96cd..0e5571531a 100644 --- a/testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.yaml +++ b/testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.yaml @@ -7,5 +7,5 @@ episodes: - 6 - 7 best-jedi: - name: "Obi-Wan" - side: "light" + name: Obi-Wan + side: light From 4d6f9610e6542dd91029c9031d2a93c5c89319bb Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 00:50:12 +0400 Subject: [PATCH 06/18] Small fixes --- ...leConfig.java => AJacksonGradleConfig.java} | 18 ++++-------------- .../gradle/spotless/JsonExtension.java | 4 ++-- .../gradle/spotless/YamlExtension.java | 6 +++--- .../gradle/spotless/YamlExtensionTest.java | 4 ++-- 4 files changed, 11 insertions(+), 21 deletions(-) rename plugin-gradle/src/main/java/com/diffplug/gradle/spotless/{JacksonGradleConfig.java => AJacksonGradleConfig.java} (71%) diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AJacksonGradleConfig.java similarity index 71% rename from plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java rename to plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AJacksonGradleConfig.java index afc0c36371..e3d5cee661 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JacksonGradleConfig.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AJacksonGradleConfig.java @@ -21,37 +21,27 @@ import com.diffplug.spotless.json.JacksonConfig; import com.diffplug.spotless.json.JacksonJsonStep; -public abstract class JacksonGradleConfig { +public abstract class AJacksonGradleConfig { protected final FormatExtension formatExtension; protected JacksonConfig jacksonConfig; protected String version = JacksonJsonStep.defaultVersion(); - public JacksonGradleConfig(JacksonConfig jacksonConfig, FormatExtension formatExtension) { + public AJacksonGradleConfig(JacksonConfig jacksonConfig, FormatExtension formatExtension) { this.formatExtension = formatExtension; this.jacksonConfig = jacksonConfig; formatExtension.addStep(createStep()); } - public JacksonGradleConfig(FormatExtension formatExtension) { - this(new JacksonConfig(), formatExtension); - } - - public JacksonGradleConfig config(JacksonConfig jacksonConfig) { - this.jacksonConfig = jacksonConfig; - formatExtension.replaceStep(createStep()); - return this; - } - - public JacksonGradleConfig feature(String feature, boolean toggle) { + public AJacksonGradleConfig feature(String feature, boolean toggle) { this.jacksonConfig.appendFeatureToToggle(Collections.singletonMap(feature, toggle)); formatExtension.replaceStep(createStep()); return this; } - public JacksonGradleConfig version(String version) { + public AJacksonGradleConfig version(String version) { this.version = version; formatExtension.replaceStep(createStep()); return this; diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java index 31f605809c..94e94c639e 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java @@ -116,7 +116,7 @@ private FormatterStep createStep() { } } - public static class JacksonJsonGradleConfig extends JacksonGradleConfig { + public static class JacksonJsonGradleConfig extends AJacksonGradleConfig { protected JacksonJsonConfig jacksonConfig; public JacksonJsonGradleConfig(JacksonJsonConfig jacksonConfig, FormatExtension formatExtension) { @@ -135,7 +135,7 @@ public JacksonJsonGradleConfig(FormatExtension formatExtension) { /** * @see com.fasterxml.jackson.core.JsonGenerator.Feature */ - public JacksonGradleConfig jsonFeature(String feature, boolean toggle) { + public AJacksonGradleConfig jsonFeature(String feature, boolean toggle) { this.jacksonConfig.appendJsonFeatureToToggle(Collections.singletonMap(feature, toggle)); formatExtension.replaceStep(createStep()); return this; diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java index 3fc12e0495..e5dc3d79ac 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java @@ -41,11 +41,11 @@ protected void setupTask(SpotlessTask task) { super.setupTask(task); } - public JacksonGradleConfig jacksonYaml() { + public AJacksonGradleConfig jacksonYaml() { return new JacksonYamlGradleConfig(this); } - public class JacksonYamlGradleConfig extends JacksonGradleConfig { + public class JacksonYamlGradleConfig extends AJacksonGradleConfig { protected JacksonYamlConfig jacksonConfig; public JacksonYamlGradleConfig(JacksonYamlConfig jacksonConfig, FormatExtension formatExtension) { @@ -65,7 +65,7 @@ public JacksonYamlGradleConfig(FormatExtension formatExtension) { /** * @see com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature */ - public JacksonGradleConfig yamlFeature(String feature, boolean toggle) { + public AJacksonGradleConfig yamlFeature(String feature, boolean toggle) { this.jacksonConfig.appendYamlFeatureToToggle(Collections.singletonMap(feature, toggle)); formatExtension.replaceStep(createStep()); return this; diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java index 79e0df0d8d..618b8d17ca 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java @@ -51,8 +51,8 @@ void testFormatYaml_WithJackson_skipDocStartMarker() throws IOException { "spotless {", " yaml {", " target 'src/**/*.yaml'", - " jacksonYaml()" + - " .yamlFeature('WRITE_DOC_START_MARKER', false)" + + " jacksonYaml()" , + " .yamlFeature('WRITE_DOC_START_MARKER', false)" , " .yamlFeature('MINIMIZE_QUOTES', true)", " }", "}"); From 38bc206a73283d0ddff1d10bb1fb45b3493edff3 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 00:53:57 +0400 Subject: [PATCH 07/18] Fix style --- .../java/com/diffplug/gradle/spotless/YamlExtensionTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java index 618b8d17ca..ee5ee33366 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java @@ -51,8 +51,8 @@ void testFormatYaml_WithJackson_skipDocStartMarker() throws IOException { "spotless {", " yaml {", " target 'src/**/*.yaml'", - " jacksonYaml()" , - " .yamlFeature('WRITE_DOC_START_MARKER', false)" , + " jacksonYaml()", + " .yamlFeature('WRITE_DOC_START_MARKER', false)", " .yamlFeature('MINIMIZE_QUOTES', true)", " }", "}"); From 949c0984671a3092219d0e7674d885bbe160f51a Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 09:35:44 +0400 Subject: [PATCH 08/18] Fix Yaml referring to Json --- .../com/diffplug/gradle/spotless/SpotlessExtension.java | 2 +- plugin-maven/CHANGES.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java index 8c3128e02d..0a31a15764 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtension.java @@ -196,7 +196,7 @@ public void json(Action closure) { /** Configures the special YAML-specific extension. */ public void yaml(Action closure) { requireNonNull(closure); - format(JsonExtension.NAME, YamlExtension.class, closure); + format(YamlExtension.NAME, YamlExtension.class, closure); } /** Configures a custom extension. */ diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 97eea5d7c0..cba82652cc 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -4,12 +4,16 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added +* Introduce `` ([#1492](https://github.com/diffplug/spotless/pull/1492)) + * **POTENTIALLY BREAKING** `JacksonYaml` is now configured with a `Map` to configure features +* Jackson (`json` and `yaml`) has new `spaceBeforeSeparator` option + * **POTENTIALLY BREAKING** `spaceBeforeSeparator` is defaulted to false while the formatter was behaving with `true` ### Fixed * 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) ### Changes * Spotless' custom build was replaced by [`maven-plugin-development`](https://github.com/britter/maven-plugin-development). ([#1496](https://github.com/diffplug/spotless/pull/1496) fixes [#554](https://github.com/diffplug/spotless/issues/554)) -# [2.30.0] - 2023-01-13 +## [2.30.0] - 2023-01-13 ### Added * Add option `editorConfigFile` for `ktLint` [#142](https://github.com/diffplug/spotless/issues/142) * **POTENTIALLY BREAKING** `ktlint` step now modifies license headers. Make sure to put `licenseHeader` *after* `ktlint`. From 37875ce62ef876c08a6357a191aa2abf80221f38 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 10:28:10 +0400 Subject: [PATCH 09/18] Rename to jackson step for both yaml and json --- .../com/diffplug/spotless/yaml/JacksonYamlStep.java | 6 ++---- .../gradle/spotless/AJacksonGradleConfig.java | 2 +- .../com/diffplug/gradle/spotless/JsonExtension.java | 12 ++++-------- .../com/diffplug/gradle/spotless/YamlExtension.java | 10 +++++----- .../diffplug/gradle/spotless/JsonExtensionTest.java | 2 +- .../diffplug/gradle/spotless/YamlExtensionTest.java | 6 +++--- ...ith_bracket.clean.no_start_marker.no_quotes.yaml} | 0 7 files changed, 16 insertions(+), 22 deletions(-) rename testlib/src/main/resources/yaml/{array_with_bracket.clean.no_start_marker.yaml => array_with_bracket.clean.no_start_marker.no_quotes.yaml} (100%) diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java index 201199fe8b..a87e40f420 100644 --- a/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java +++ b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlStep.java @@ -30,6 +30,7 @@ * Simple YAML formatter which reformats the file according to Jackson YAMLFactory. */ // https://stackoverflow.com/questions/14515994/convert-json-string-to-pretty-print-json-output-using-jackson +// https://stackoverflow.com/questions/60891174/i-want-to-load-a-yaml-file-possibly-edit-the-data-and-then-dump-it-again-how public class JacksonYamlStep { static final String MAVEN_COORDINATE = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:"; // https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml @@ -44,6 +45,7 @@ public static String defaultVersion() { public static FormatterStep create(JacksonYamlConfig jacksonConfig, String jacksonVersion, Provisioner provisioner) { + Objects.requireNonNull(jacksonConfig, "jacksonConfig cannot be null"); Objects.requireNonNull(provisioner, "provisioner cannot be null"); return FormatterStep.createLazy("yaml", () -> new State(jacksonConfig, jacksonVersion, provisioner), @@ -66,10 +68,6 @@ private State(JacksonYamlConfig jacksonConfig, Provisioner provisioner) throws IOException { this.jacksonConfig = jacksonConfig; - if (jacksonConfig == null) { - throw new IllegalArgumentException("ARG"); - } - this.jarState = JarState.from(JacksonYamlStep.MAVEN_COORDINATE + jacksonVersion, provisioner); } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AJacksonGradleConfig.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AJacksonGradleConfig.java index e3d5cee661..c017d41d04 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AJacksonGradleConfig.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/AJacksonGradleConfig.java @@ -28,11 +28,11 @@ public abstract class AJacksonGradleConfig { protected String version = JacksonJsonStep.defaultVersion(); + // Make sure to call 'formatExtension.addStep(createStep());' in the extented constructors public AJacksonGradleConfig(JacksonConfig jacksonConfig, FormatExtension formatExtension) { this.formatExtension = formatExtension; this.jacksonConfig = jacksonConfig; - formatExtension.addStep(createStep()); } public AJacksonGradleConfig feature(String feature, boolean toggle) { diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java index 94e94c639e..b964fcb54d 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java @@ -51,7 +51,7 @@ public GsonConfig gson() { return new GsonConfig(); } - public JacksonJsonGradleConfig jacksonJson() { + public JacksonJsonGradleConfig jackson() { return new JacksonJsonGradleConfig(this); } @@ -123,9 +123,7 @@ public JacksonJsonGradleConfig(JacksonJsonConfig jacksonConfig, FormatExtension super(jacksonConfig, formatExtension); this.jacksonConfig = jacksonConfig; - if (jacksonConfig == null) { - throw new IllegalArgumentException("ARG2"); - } + formatExtension.addStep(createStep()); } public JacksonJsonGradleConfig(FormatExtension formatExtension) { @@ -141,11 +139,9 @@ public AJacksonGradleConfig jsonFeature(String feature, boolean toggle) { return this; } + // 'final' as it is called in the constructor @Override - protected FormatterStep createStep() { - if (jacksonConfig == null) { - throw new IllegalArgumentException("ARG3"); - } + protected final FormatterStep createStep() { return JacksonJsonStep.create(jacksonConfig, version, formatExtension.provisioner()); } } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java index e5dc3d79ac..26b742f02a 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java @@ -19,6 +19,7 @@ import javax.inject.Inject; +import com.diffplug.common.base.Throwables; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.json.JacksonJsonStep; import com.diffplug.spotless.yaml.JacksonYamlConfig; @@ -41,7 +42,7 @@ protected void setupTask(SpotlessTask task) { super.setupTask(task); } - public AJacksonGradleConfig jacksonYaml() { + public AJacksonGradleConfig jackson() { return new JacksonYamlGradleConfig(this); } @@ -53,9 +54,7 @@ public JacksonYamlGradleConfig(JacksonYamlConfig jacksonConfig, FormatExtension this.jacksonConfig = jacksonConfig; - if (jacksonConfig == null) { - throw new IllegalArgumentException("ARG"); - } + formatExtension.addStep(createStep()); } public JacksonYamlGradleConfig(FormatExtension formatExtension) { @@ -71,8 +70,9 @@ public AJacksonGradleConfig yamlFeature(String feature, boolean toggle) { return this; } + // 'final' as it is called in the constructor @Override - protected FormatterStep createStep() { + protected final FormatterStep createStep() { return JacksonYamlStep.create(jacksonConfig, version, provisioner()); } } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JsonExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JsonExtensionTest.java index 945c72cf75..a878615eaa 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JsonExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JsonExtensionTest.java @@ -149,7 +149,7 @@ void jacksonFormattingWithSortingByKeys() throws IOException { "spotless {", " json {", " target 'src/**/*.json'", - " jacksonJson().feature('ORDER_MAP_ENTRIES_BY_KEYS', true)", + " jackson().feature('ORDER_MAP_ENTRIES_BY_KEYS', true)", " }", "}"); setFile("src/main/resources/example.json").toResource("json/sortByKeysBefore.json"); diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java index ee5ee33366..455dfc6dcf 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java @@ -31,7 +31,7 @@ void testFormatYaml_WithJackson_defaultConfig_separatorComments() throws IOExcep "spotless {", " yaml {", " target 'src/**/*.yaml'", - " jacksonYaml()", + " jackson()", " }", "}"); setFile("src/main/resources/example.yaml").toResource("yaml/separator_comments.yaml"); @@ -51,14 +51,14 @@ void testFormatYaml_WithJackson_skipDocStartMarker() throws IOException { "spotless {", " yaml {", " target 'src/**/*.yaml'", - " jacksonYaml()", + " jackson()", " .yamlFeature('WRITE_DOC_START_MARKER', false)", " .yamlFeature('MINIMIZE_QUOTES', true)", " }", "}"); setFile("src/main/resources/example.yaml").toResource("yaml/array_with_bracket.yaml"); gradleRunner().withArguments("spotlessApply").build(); - assertFile("src/main/resources/example.yaml").sameAsResource("yaml/array_with_bracket.clean.no_start_marker.yaml"); + assertFile("src/main/resources/example.yaml").sameAsResource("yaml/array_with_bracket.clean.no_start_marker.no_quotes.yaml"); } } diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.no_quotes.yaml similarity index 100% rename from testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.yaml rename to testlib/src/main/resources/yaml/array_with_bracket.clean.no_start_marker.no_quotes.yaml From a22109e5e4b3e7daf4ae41b308d39bead18a06ef Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 10:41:53 +0400 Subject: [PATCH 10/18] spotlessApply --- .../spotless/glue/yaml/JacksonYamlFormatterFunc.java | 5 ----- .../java/com/diffplug/gradle/spotless/YamlExtension.java | 1 - .../java/com/diffplug/gradle/spotless/YamlExtensionTest.java | 2 +- plugin-maven/README.md | 4 ++-- .../test/java/com/diffplug/spotless/maven/yaml/YamlTest.java | 1 - 5 files changed, 3 insertions(+), 10 deletions(-) diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java index 3986374c9e..0cf4591717 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java @@ -57,11 +57,6 @@ protected JsonFactory makeJsonFactory() { @Override protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { - // We may consider adding manually an initial '---' prefix to help management of multiple documents - // if (!input.trim().startsWith("---")) { - // input = "---" + "\n" + input; - // } - try { // https://stackoverflow.com/questions/25222327/deserialize-pojos-from-multiple-yaml-documents-in-a-single-file-in-jackson // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-375328648 diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java index 26b742f02a..bf268914fc 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java @@ -19,7 +19,6 @@ import javax.inject.Inject; -import com.diffplug.common.base.Throwables; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.json.JacksonJsonStep; import com.diffplug.spotless.yaml.JacksonYamlConfig; diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java index 455dfc6dcf..7baddc4177 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java @@ -57,7 +57,7 @@ void testFormatYaml_WithJackson_skipDocStartMarker() throws IOException { " }", "}"); setFile("src/main/resources/example.yaml").toResource("yaml/array_with_bracket.yaml"); - gradleRunner().withArguments("spotlessApply").build(); + gradleRunner().withArguments("spotlessApply", "--stacktrace").build(); assertFile("src/main/resources/example.yaml").sameAsResource("yaml/array_with_bracket.clean.no_start_marker.no_quotes.yaml"); } diff --git a/plugin-maven/README.md b/plugin-maven/README.md index e76d424611..7673a440c6 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -12,8 +12,8 @@ output = [ ].join('\n'); --> [![Maven central](https://img.shields.io/badge/mavencentral-com.diffplug.spotless%3Aspotless--maven--plugin-blue.svg)](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.diffplug.spotless%22%20AND%20a%3A%22spotless-maven-plugin%22) -[![Javadoc](https://img.shields.io/badge/javadoc-yes-blue.svg)](https://javadoc.io/doc/com.diffplug.spotless/spotless-maven-plugin/2.29.0/index.html) -[![Changelog](https://img.shields.io/badge/changelog-2.29.0-brightgreen.svg)](CHANGES.md) +[![Javadoc](https://img.shields.io/badge/javadoc-yes-blue.svg)](https://javadoc.io/doc/com.diffplug.spotless/spotless-maven-plugin/2.30.0/index.html) +[![Changelog](https://img.shields.io/badge/changelog-2.30.0-brightgreen.svg)](CHANGES.md) [![Circle CI](https://circleci.com/gh/diffplug/spotless/tree/main.svg?style=shield)](https://circleci.com/gh/diffplug/spotless/tree/main) [![Live chat](https://img.shields.io/badge/gitter-chat-brightgreen.svg)](https://gitter.im/diffplug/spotless) diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java index 084f1495eb..aaea2c65b1 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java @@ -19,7 +19,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.diffplug.spotless.ProcessRunner; import com.diffplug.spotless.maven.MavenIntegrationHarness; public class YamlTest extends MavenIntegrationHarness { From 7bc34f48328a42bdc26a58c2b1d22f2b68892256 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 11:46:36 +0400 Subject: [PATCH 11/18] Switch from ObjectNode to Map to enable SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS --- .../glue/json/AJacksonFormatterFunc.java | 16 ++++++++------ .../glue/json/JacksonJsonFormatterFunc.java | 2 +- .../diffplug/spotless/json/JacksonConfig.java | 2 +- .../spotless/json/JacksonJsonConfig.java | 4 ++-- .../spotless/yaml/JacksonYamlConfig.java | 4 ++-- .../gradle/spotless/JsonExtension.java | 2 +- .../gradle/spotless/YamlExtension.java | 3 +-- .../spotless/maven/json/JsonTest.java | 2 +- .../spotless/maven/yaml/YamlTest.java | 9 -------- .../json/sortByKeysAfter_Jackson.json | 22 ++++++++----------- ...sAfter_Jackson_spaceAfterKeySeparator.json | 22 ++++++++----------- ...th_bracket.clean.spaceBeforeSeparator.yaml | 12 ---------- 12 files changed, 36 insertions(+), 64 deletions(-) delete mode 100644 testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java index a835c85f9a..a41ecf90d2 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java @@ -16,10 +16,11 @@ package com.diffplug.spotless.glue.json; import java.io.IOException; +import java.util.Map; import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.PrettyPrinter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; @@ -48,8 +49,11 @@ public String apply(String input) throws Exception { protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { try { - ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); - return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectNode); + // ObjectNode is not compatible with SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS + Map objectNode = objectMapper.readValue(input, Map.class); + String output = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectNode); + + return output; } catch (JsonProcessingException e) { throw new AssertionError("Unable to format. input='" + input + "'", e); } @@ -65,7 +69,7 @@ protected ObjectMapper makeObjectMapper() { JsonFactory jsonFactory = makeJsonFactory(); ObjectMapper objectMapper = new ObjectMapper(jsonFactory); - objectMapper.setDefaultPrettyPrinter(makePrinter()); + objectMapper.setDefaultPrettyPrinter(makePrettyPrinter()); // Configure the ObjectMapper // https://github.com/FasterXML/jackson-databind#commonly-used-features @@ -76,12 +80,10 @@ protected ObjectMapper makeObjectMapper() { objectMapper.configure(feature, toggle); }); - new JsonFactory().configure(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, true); - return objectMapper; } - protected DefaultPrettyPrinter makePrinter() { + protected PrettyPrinter makePrettyPrinter() { return new DefaultPrettyPrinter(); } } diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java index 5aadcc568f..ae455fbbb4 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java @@ -57,7 +57,7 @@ protected JsonFactory makeJsonFactory() { } @Override - protected DefaultPrettyPrinter makePrinter() { + protected DefaultPrettyPrinter makePrettyPrinter() { boolean spaceBeforeSeparator = jacksonConfig.isSpaceBeforeSeparator(); // DefaultIndenter default constructor relies on 2 whitespaces as default tabulation diff --git a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java index 250b77d1f1..f0dba8f072 100644 --- a/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java +++ b/lib/src/main/java/com/diffplug/spotless/json/JacksonConfig.java @@ -36,7 +36,7 @@ public class JacksonConfig implements Serializable { DEFAULT_FEATURE_TOGGLES = defaultFeatureToggles; } - protected Map featureToToggle = new LinkedHashMap<>(); + protected Map featureToToggle = new LinkedHashMap<>(DEFAULT_FEATURE_TOGGLES); public Map getFeatureToToggle() { return Collections.unmodifiableMap(featureToToggle); diff --git a/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonConfig.java b/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonConfig.java index 50b28605d1..efff594663 100644 --- a/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonConfig.java +++ b/lib/src/main/java/com/diffplug/spotless/json/JacksonJsonConfig.java @@ -36,14 +36,14 @@ public Map getJsonFeatureToToggle() { } /** - * @see com.fasterxml.jackson.core.JsonGenerator.Feature + * Refers to com.fasterxml.jackson.core.JsonGenerator.Feature */ public void setJsonFeatureToToggle(Map jsonFeatureToToggle) { this.jsonFeatureToToggle = jsonFeatureToToggle; } /** - * @see com.fasterxml.jackson.core.JsonGenerator.Feature + * Refers to com.fasterxml.jackson.core.JsonGenerator.Feature */ public void appendJsonFeatureToToggle(Map features) { this.jsonFeatureToToggle.putAll(features); diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlConfig.java b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlConfig.java index 2463b9603f..166ee5f307 100644 --- a/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlConfig.java +++ b/lib/src/main/java/com/diffplug/spotless/yaml/JacksonYamlConfig.java @@ -34,14 +34,14 @@ public Map getYamlFeatureToToggle() { } /** - * @see com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature + * Refers to com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature */ public void setYamlFeatureToToggle(Map yamlFeatureToToggle) { this.yamlFeatureToToggle = yamlFeatureToToggle; } /** - * @see com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature + * Refers to com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature */ public void appendYamlFeatureToToggle(Map features) { this.yamlFeatureToToggle.putAll(features); diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java index b964fcb54d..ef0e993d37 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java @@ -131,7 +131,7 @@ public JacksonJsonGradleConfig(FormatExtension formatExtension) { } /** - * @see com.fasterxml.jackson.core.JsonGenerator.Feature + * @Refers to com.fasterxml.jackson.core.JsonGenerator.Feature */ public AJacksonGradleConfig jsonFeature(String feature, boolean toggle) { this.jacksonConfig.appendJsonFeatureToToggle(Collections.singletonMap(feature, toggle)); diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java index bf268914fc..7be3264102 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java @@ -25,7 +25,6 @@ import com.diffplug.spotless.yaml.JacksonYamlStep; public class YamlExtension extends FormatExtension { - private static final String DEFAULT_GSON_VERSION = JacksonJsonStep.defaultVersion(); static final String NAME = "yaml"; @Inject @@ -61,7 +60,7 @@ public JacksonYamlGradleConfig(FormatExtension formatExtension) { } /** - * @see com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature + * Refers to com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature */ public AJacksonGradleConfig yamlFeature(String feature, boolean toggle) { this.jacksonConfig.appendYamlFeatureToToggle(Collections.singletonMap(feature, toggle)); diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java index 47de001a73..1897cc764a 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/json/JsonTest.java @@ -76,7 +76,7 @@ public void testFormatJson_WithJackson_sortByKeys() throws Exception { setFile("json_test.json").toResource("json/sortByKeysBefore.json"); - mavenRunner().withArguments("spotless:apply").runNoError(); + mavenRunner().withArguments("spotless:apply", "-X").runNoError(); assertFile("json_test.json").sameAsResource("json/sortByKeysAfter_Jackson.json"); } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java index aaea2c65b1..6af4d09ce9 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java @@ -42,15 +42,6 @@ public void testFormatYaml_WithJackson_defaultConfig_arrayBrackets() throws Exce assertFile("yaml_test.yaml").sameAsResource("yaml/array_with_bracket.clean.yaml"); } - @Test - public void testFormatYaml_WithJackson_defaultConfig_arrayBrackets_spaceBeforeSeparator() throws Exception { - writePomWithYamlSteps("true"); - - setFile("yaml_test.yaml").toResource("yaml/array_with_bracket.yaml"); - mavenRunner().withArguments("spotless:apply").runNoError(); - assertFile("yaml_test.yaml").sameAsResource("yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml"); - } - @Test public void testFormatYaml_WithJackson_defaultConfig_multipleDocuments() throws Exception { writePomWithYamlSteps(""); diff --git a/testlib/src/main/resources/json/sortByKeysAfter_Jackson.json b/testlib/src/main/resources/json/sortByKeysAfter_Jackson.json index c4a48de2f2..3af39fd0fb 100644 --- a/testlib/src/main/resources/json/sortByKeysAfter_Jackson.json +++ b/testlib/src/main/resources/json/sortByKeysAfter_Jackson.json @@ -1,19 +1,15 @@ { + "A": 1, + "X": 2, + "_arraysNotSorted": [ 3, 2, 1 ], + "a": 3, + "c": 4, + "x": 5, + "z": { "A": 1, "X": 2, - "_arraysNotSorted": [ - 3, - 2, - 1 - ], "a": 3, "c": 4, - "x": 5, - "z": { - "A": 1, - "X": 2, - "a": 3, - "c": 4, - "x": 5 - } + "x": 5 + } } diff --git a/testlib/src/main/resources/json/sortByKeysAfter_Jackson_spaceAfterKeySeparator.json b/testlib/src/main/resources/json/sortByKeysAfter_Jackson_spaceAfterKeySeparator.json index c4a48de2f2..3af39fd0fb 100644 --- a/testlib/src/main/resources/json/sortByKeysAfter_Jackson_spaceAfterKeySeparator.json +++ b/testlib/src/main/resources/json/sortByKeysAfter_Jackson_spaceAfterKeySeparator.json @@ -1,19 +1,15 @@ { + "A": 1, + "X": 2, + "_arraysNotSorted": [ 3, 2, 1 ], + "a": 3, + "c": 4, + "x": 5, + "z": { "A": 1, "X": 2, - "_arraysNotSorted": [ - 3, - 2, - 1 - ], "a": 3, "c": 4, - "x": 5, - "z": { - "A": 1, - "X": 2, - "a": 3, - "c": 4, - "x": 5 - } + "x": 5 + } } diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml deleted file mode 100644 index 7dc9255e06..0000000000 --- a/testlib/src/main/resources/yaml/array_with_bracket.clean.spaceBeforeSeparator.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -episodes: -- 1 -- 2 -- 3 -- 4 -- 5 -- 6 -- 7 -best-jedi : - name : "Obi-Wan" - side : "light" From 8d2cdd3d5c800161fa8149a8c4aa6f9d7d596849 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 12:33:38 +0400 Subject: [PATCH 12/18] Fix management of multiple documents YAML --- .../glue/json/AJacksonFormatterFunc.java | 2 +- .../glue/yaml/JacksonYamlFormatterFunc.java | 31 +++++---- .../spotless/json/JsonSimpleStep.java | 6 +- .../gradle/spotless/YamlExtensionTest.java | 67 +++++++++++++++---- .../resources/yaml/array_at_root.clean.yaml | 5 ++ .../main/resources/yaml/array_at_root.yaml | 7 ++ .../yaml/multiple_documents.clean.yaml | 12 ++-- .../resources/yaml/multiple_documents.yaml | 14 ++-- 8 files changed, 99 insertions(+), 45 deletions(-) create mode 100644 testlib/src/main/resources/yaml/array_at_root.clean.yaml create mode 100644 testlib/src/main/resources/yaml/array_at_root.yaml diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java index a41ecf90d2..244ce05a9e 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java @@ -55,7 +55,7 @@ protected String format(ObjectMapper objectMapper, String input) throws IllegalA return output; } catch (JsonProcessingException e) { - throw new AssertionError("Unable to format. input='" + input + "'", e); + throw new IllegalArgumentException("Unable to format. input='" + input + "'", e); } } diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java index 0cf4591717..96012e1041 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java @@ -15,12 +15,18 @@ */ package com.diffplug.spotless.glue.yaml; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.util.List; import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.SequenceWriter; +import com.fasterxml.jackson.databind.node.ContainerNode; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fasterxml.jackson.dataformat.yaml.YAMLFactoryBuilder; import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; @@ -57,24 +63,21 @@ protected JsonFactory makeJsonFactory() { @Override protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { + //if (true) + // throw new IllegalArgumentException("input = \r\n" + input); try { // https://stackoverflow.com/questions/25222327/deserialize-pojos-from-multiple-yaml-documents-in-a-single-file-in-jackson // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-375328648 - // 2023-01: For now, we get 'Cannot deserialize value of type `com.fasterxml.jackson.databind.node.ObjectNode` from Array value' - // JsonParser yamlParser = objectMapper.getFactory().createParser(input); - // List docs = objectMapper.readValues(yamlParser, ObjectNode.class).readAll(); - // return objectMapper.writeValueAsString(docs); + JsonParser yamlParser = objectMapper.getFactory().createParser(input); + List documents = objectMapper.readValues(yamlParser, ContainerNode.class).readAll(); - // A JsonNode may keep the comments from the input node - // JsonNode jsonNode = objectMapper.readTree(input); - //Not 'toPrettyString' as one could require no INDENT_OUTPUT - // return jsonNode.toPrettyString(); - ObjectNode objectNode = objectMapper.readValue(input, ObjectNode.class); - String outputFromjackson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectNode); - - return outputFromjackson; + // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-554265055 + // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-554265055 + StringWriter stringWriter = new StringWriter(); + objectMapper.writer().writeValues(stringWriter).writeAll(documents).close(); + return stringWriter.toString(); } catch (JsonProcessingException e) { - throw new AssertionError("Unable to format. input='" + input + "'", e); + throw new IllegalArgumentException("Unable to format. input='" + input + "'", e); } } } diff --git a/lib/src/main/java/com/diffplug/spotless/json/JsonSimpleStep.java b/lib/src/main/java/com/diffplug/spotless/json/JsonSimpleStep.java index a970149133..1f4db3e059 100644 --- a/lib/src/main/java/com/diffplug/spotless/json/JsonSimpleStep.java +++ b/lib/src/main/java/com/diffplug/spotless/json/JsonSimpleStep.java @@ -81,7 +81,7 @@ FormatterFunc toFormatter() { return format(arrayConstructor, arrayToString, s); } - throw new AssertionError(String.format("Unable to determine JSON type, expected a '{' or '[' but found '%s'", first)); + throw new IllegalArgumentException(String.format("Unable to determine JSON type, expected a '{' or '[' but found '%s'", first)); }; } @@ -89,8 +89,8 @@ private String format(Constructor constructor, Method toString, String input) try { Object parsed = constructor.newInstance(input); return toString.invoke(parsed, indentSpaces) + "\n"; - } catch (InvocationTargetException ex) { - throw new AssertionError("Unable to format JSON", ex.getCause()); + } catch (InvocationTargetException e) { + throw new IllegalArgumentException("Unable to format JSON", e); } } } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java index 7baddc4177..295934dd26 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java @@ -43,22 +43,63 @@ void testFormatYaml_WithJackson_defaultConfig_separatorComments() throws IOExcep @Test void testFormatYaml_WithJackson_skipDocStartMarker() throws IOException { setFile("build.gradle").toLines( - "plugins {", - " id 'java'", - " id 'com.diffplug.spotless'", - "}", - "repositories { mavenCentral() }", - "spotless {", - " yaml {", - " target 'src/**/*.yaml'", - " jackson()", - " .yamlFeature('WRITE_DOC_START_MARKER', false)", - " .yamlFeature('MINIMIZE_QUOTES', true)", - " }", - "}"); + "plugins {", + " id 'java'", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "spotless {", + " yaml {", + " target 'src/**/*.yaml'", + " jackson()", + " .yamlFeature('WRITE_DOC_START_MARKER', false)", + " .yamlFeature('MINIMIZE_QUOTES', true)", + " }", + "}"); setFile("src/main/resources/example.yaml").toResource("yaml/array_with_bracket.yaml"); gradleRunner().withArguments("spotlessApply", "--stacktrace").build(); assertFile("src/main/resources/example.yaml").sameAsResource("yaml/array_with_bracket.clean.no_start_marker.no_quotes.yaml"); } + @Test + void testFormatYaml_WithJackson_multipleDocuments() throws IOException { + setFile("build.gradle").toLines( + "plugins {", + " id 'java'", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "spotless {", + " yaml {", + " target 'src/**/*.yaml'", + " jackson()", + " .yamlFeature('MINIMIZE_QUOTES', true)", + " }", + "}"); + setFile("src/main/resources/example.yaml").toResource("yaml/multiple_documents.yaml"); + gradleRunner().withArguments("spotlessApply", "--stacktrace").build(); + assertFile("src/main/resources/example.yaml").sameAsResource("yaml/multiple_documents.clean.jackson.yaml"); + } + + + @Test + void testFormatYaml_WithJackson_arrayAtRoot() throws IOException { + setFile("build.gradle").toLines( + "plugins {", + " id 'java'", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "spotless {", + " yaml {", + " target 'src/**/*.yaml'", + " jackson()", + " }", + "}"); + setFile("src/main/resources/example.yaml").toResource("yaml/array_at_root.yaml"); + gradleRunner().withArguments("spotlessApply", "--stacktrace").build(); + assertFile("src/main/resources/example.yaml").sameAsResource("yaml/array_at_root.clean.yaml"); + } + + } diff --git a/testlib/src/main/resources/yaml/array_at_root.clean.yaml b/testlib/src/main/resources/yaml/array_at_root.clean.yaml new file mode 100644 index 0000000000..f9bae04114 --- /dev/null +++ b/testlib/src/main/resources/yaml/array_at_root.clean.yaml @@ -0,0 +1,5 @@ +--- +- key1: "value1" + key2: "value2" +- key3: "value3" + key4: "value4" diff --git a/testlib/src/main/resources/yaml/array_at_root.yaml b/testlib/src/main/resources/yaml/array_at_root.yaml new file mode 100644 index 0000000000..b26f6bb246 --- /dev/null +++ b/testlib/src/main/resources/yaml/array_at_root.yaml @@ -0,0 +1,7 @@ +- key1: value1 + key2: value2 + + +- key3: value3 + key4: value4 + diff --git a/testlib/src/main/resources/yaml/multiple_documents.clean.yaml b/testlib/src/main/resources/yaml/multiple_documents.clean.yaml index 45e0b0916b..3651473955 100644 --- a/testlib/src/main/resources/yaml/multiple_documents.clean.yaml +++ b/testlib/src/main/resources/yaml/multiple_documents.clean.yaml @@ -1,8 +1,8 @@ ---- -document: this is document 1 - ---- -document: this is document 2 +# Document 1 +key1: value1 +key2: value2 --- -document: this is document 3 \ No newline at end of file +# Document 2 +key3: value3 +key4: value4 diff --git a/testlib/src/main/resources/yaml/multiple_documents.yaml b/testlib/src/main/resources/yaml/multiple_documents.yaml index 51f14a5862..3651473955 100644 --- a/testlib/src/main/resources/yaml/multiple_documents.yaml +++ b/testlib/src/main/resources/yaml/multiple_documents.yaml @@ -1,10 +1,8 @@ -document: this is document 1 ---- - -document: this is document 2 - +# Document 1 +key1: value1 +key2: value2 --- - - -document: this is document 3 \ No newline at end of file +# Document 2 +key3: value3 +key4: value4 From a3693e78c1326a281dac76de9327515243d3f27e Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 12:36:06 +0400 Subject: [PATCH 13/18] spotlessApply --- .../glue/json/AJacksonFormatterFunc.java | 1 - .../glue/yaml/JacksonYamlFormatterFunc.java | 3 - .../spotless/json/JsonSimpleStep.java | 2 +- .../gradle/spotless/YamlExtension.java | 1 - .../gradle/spotless/YamlExtensionTest.java | 74 +++++++++---------- 5 files changed, 37 insertions(+), 44 deletions(-) diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java index 244ce05a9e..6f363ad1b7 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java @@ -24,7 +24,6 @@ import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.json.JacksonConfig; diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java index 96012e1041..edb350c559 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java @@ -15,17 +15,14 @@ */ package com.diffplug.spotless.glue.yaml; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.StringWriter; -import java.nio.charset.StandardCharsets; import java.util.List; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SequenceWriter; import com.fasterxml.jackson.databind.node.ContainerNode; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fasterxml.jackson.dataformat.yaml.YAMLFactoryBuilder; diff --git a/lib/src/main/java/com/diffplug/spotless/json/JsonSimpleStep.java b/lib/src/main/java/com/diffplug/spotless/json/JsonSimpleStep.java index 1f4db3e059..85ccbfa6e2 100644 --- a/lib/src/main/java/com/diffplug/spotless/json/JsonSimpleStep.java +++ b/lib/src/main/java/com/diffplug/spotless/json/JsonSimpleStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 DiffPlug + * Copyright 2021-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java index 7be3264102..abc2dce359 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java @@ -20,7 +20,6 @@ import javax.inject.Inject; import com.diffplug.spotless.FormatterStep; -import com.diffplug.spotless.json.JacksonJsonStep; import com.diffplug.spotless.yaml.JacksonYamlConfig; import com.diffplug.spotless.yaml.JacksonYamlStep; diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java index 295934dd26..82801eb0fd 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java @@ -43,19 +43,19 @@ void testFormatYaml_WithJackson_defaultConfig_separatorComments() throws IOExcep @Test void testFormatYaml_WithJackson_skipDocStartMarker() throws IOException { setFile("build.gradle").toLines( - "plugins {", - " id 'java'", - " id 'com.diffplug.spotless'", - "}", - "repositories { mavenCentral() }", - "spotless {", - " yaml {", - " target 'src/**/*.yaml'", - " jackson()", - " .yamlFeature('WRITE_DOC_START_MARKER', false)", - " .yamlFeature('MINIMIZE_QUOTES', true)", - " }", - "}"); + "plugins {", + " id 'java'", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "spotless {", + " yaml {", + " target 'src/**/*.yaml'", + " jackson()", + " .yamlFeature('WRITE_DOC_START_MARKER', false)", + " .yamlFeature('MINIMIZE_QUOTES', true)", + " }", + "}"); setFile("src/main/resources/example.yaml").toResource("yaml/array_with_bracket.yaml"); gradleRunner().withArguments("spotlessApply", "--stacktrace").build(); assertFile("src/main/resources/example.yaml").sameAsResource("yaml/array_with_bracket.clean.no_start_marker.no_quotes.yaml"); @@ -64,42 +64,40 @@ void testFormatYaml_WithJackson_skipDocStartMarker() throws IOException { @Test void testFormatYaml_WithJackson_multipleDocuments() throws IOException { setFile("build.gradle").toLines( - "plugins {", - " id 'java'", - " id 'com.diffplug.spotless'", - "}", - "repositories { mavenCentral() }", - "spotless {", - " yaml {", - " target 'src/**/*.yaml'", - " jackson()", - " .yamlFeature('MINIMIZE_QUOTES', true)", - " }", - "}"); + "plugins {", + " id 'java'", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "spotless {", + " yaml {", + " target 'src/**/*.yaml'", + " jackson()", + " .yamlFeature('MINIMIZE_QUOTES', true)", + " }", + "}"); setFile("src/main/resources/example.yaml").toResource("yaml/multiple_documents.yaml"); gradleRunner().withArguments("spotlessApply", "--stacktrace").build(); assertFile("src/main/resources/example.yaml").sameAsResource("yaml/multiple_documents.clean.jackson.yaml"); } - @Test void testFormatYaml_WithJackson_arrayAtRoot() throws IOException { setFile("build.gradle").toLines( - "plugins {", - " id 'java'", - " id 'com.diffplug.spotless'", - "}", - "repositories { mavenCentral() }", - "spotless {", - " yaml {", - " target 'src/**/*.yaml'", - " jackson()", - " }", - "}"); + "plugins {", + " id 'java'", + " id 'com.diffplug.spotless'", + "}", + "repositories { mavenCentral() }", + "spotless {", + " yaml {", + " target 'src/**/*.yaml'", + " jackson()", + " }", + "}"); setFile("src/main/resources/example.yaml").toResource("yaml/array_at_root.yaml"); gradleRunner().withArguments("spotlessApply", "--stacktrace").build(); assertFile("src/main/resources/example.yaml").sameAsResource("yaml/array_at_root.clean.yaml"); } - } From c613302d0b1d4edece0c1d6a9a408aea716cedf4 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 13:01:25 +0400 Subject: [PATCH 14/18] Improve documentation, fix tests --- plugin-gradle/CHANGES.md | 2 + plugin-gradle/README.md | 65 +++++++++++++++++-- plugin-maven/README.md | 20 ++++-- .../spotless/maven/json/JacksonJson.java | 4 ++ .../multiple_documents.clean.jackson.yaml | 6 +- 5 files changed, 83 insertions(+), 14 deletions(-) diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 63e5b43d74..94d7a90409 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -4,6 +4,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added +* Support `jackson()` for YAML files ([#1492](https://github.com/diffplug/spotless/pull/1492)) +* Support `jackson()` for JSON files ([#1492](https://github.com/diffplug/spotless/pull/1492)) ### Fixed * 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) ### Changes diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index f2567a5924..e1bd2fe0dd 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -737,11 +737,12 @@ For details, see the [npm detection](#npm-detection) and [`.npmrc` detection](#n ```gradle spotless { json { - target 'src/**/*.json' // you have to set the target manually - simple() // has its own section below + target 'src/**/*.json' // you have to set the target manually + simple() // has its own section below prettier().config(['parser': 'json']) // see Prettier section below - eclipseWtp('json') // see Eclipse web tools platform section - gson() // has its own section below + eclipseWtp('json') // see Eclipse web tools platform section + gson() // has its own section below + jackson() // has its own section below } } ``` @@ -780,10 +781,60 @@ spotless { Notes: * There's no option in Gson to leave HTML as-is (i.e. escaped HTML would remain escaped, raw would remain raw). Either -all HTML characters are written escaped or none. Set `escapeHtml` if you prefer the former. + all HTML characters are written escaped or none. Set `escapeHtml` if you prefer the former. * `sortByKeys` will apply lexicographic order on the keys of the input JSON. See the -[javadoc of String](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#compareTo(java.lang.String)) -for details. + [javadoc of String](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#compareTo(java.lang.String)) + for details. + +### Jackson + +Uses Jackson for json files. + +```gradle +spotless { + json { + target 'src/**/*.json' + jackson() + .spaceBeforeSeparator(false) // optional: add a whitespace before key separator. False by default + .feature('INDENT_OUTPUT', true) // optional: true by default + .feature('ORDER_MAP_ENTRIES_BY_KEYS', true) // optional: false by default + .feature('ANY_OTHER_FEATURE', true|false) // optional: any SerializationFeature can be toggled on or off + .jsonFeature('ANY_OTHER_FEATURE', true|false) // any JsonGenerator.Feature can be toggled on or off + } +} +``` + + +## YAML + +- `com.diffplug.gradle.spotless.YamlExtension` [javadoc](https://javadoc.io/doc/com.diffplug.spotless/spotless-plugin-gradle/6.13.0/com/diffplug/gradle/spotless/JsonExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/YamlExtension.java) + +```gradle +spotless { + yaml { + target 'src/**/*.yaml' // you have to set the target manually + jackson() // has its own section below + } +} +``` + +### Jackson + +Uses Jackson for `yaml` files. + +```gradle +spotless { + yaml { + target 'src/**/*.yaml' + jackson() + .spaceBeforeSeparator(false) // optional: add a whitespace before key separator. False by default + .feature('INDENT_OUTPUT', true) // optional: true by default + .feature('ORDER_MAP_ENTRIES_BY_KEYS', true) // optional: false by default + .feature('ANY_OTHER_FEATURE', true|false) // optional: any SerializationFeature can be toggled on or off + .yamlFeature('ANY_OTHER_FEATURE', true|false) // any YAMLGenerator.Feature can be toggled on or off + } +} +``` diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 7673a440c6..37d1046b1d 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -907,11 +907,15 @@ Uses Jackson for formatting. 2.14.1 - true - false - true|false + true + false + true|false - false + + false + true|false + + false ``` @@ -944,9 +948,13 @@ Uses Jackson and YAMLFactory to pretty print objects: true false - false - true|false + true|false + + true + false + true|false + false ``` diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java index 9bca852754..ecf925ddbe 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/JacksonJson.java @@ -41,11 +41,15 @@ public class JacksonJson implements FormatterStepFactory { @Parameter private Map features = Collections.emptyMap(); + @Parameter + private Map jsonFeatures = Collections.emptyMap(); + @Override public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { JacksonJsonConfig jacksonConfig = new JacksonJsonConfig(); jacksonConfig.appendFeatureToToggle(features); + jacksonConfig.appendJsonFeatureToToggle(jsonFeatures); jacksonConfig.setSpaceBeforeSeparator(spaceBeforeSeparator); return JacksonJsonStep diff --git a/testlib/src/main/resources/yaml/multiple_documents.clean.jackson.yaml b/testlib/src/main/resources/yaml/multiple_documents.clean.jackson.yaml index aa731919b4..ff56b4f77a 100644 --- a/testlib/src/main/resources/yaml/multiple_documents.clean.jackson.yaml +++ b/testlib/src/main/resources/yaml/multiple_documents.clean.jackson.yaml @@ -1,2 +1,6 @@ --- -document: "this is document 1" +key1: "value1" +key2: "value2" +--- +key3: "value3" +key4: "value4" From 97ecda34a74bb07e86fa3f4db38e70b9352f49ed Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 13:27:27 +0400 Subject: [PATCH 15/18] Fix Javadoc --- .../main/java/com/diffplug/gradle/spotless/JsonExtension.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java index ef0e993d37..1e9de2e831 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JsonExtension.java @@ -131,7 +131,7 @@ public JacksonJsonGradleConfig(FormatExtension formatExtension) { } /** - * @Refers to com.fasterxml.jackson.core.JsonGenerator.Feature + * Refers to com.fasterxml.jackson.core.JsonGenerator.Feature */ public AJacksonGradleConfig jsonFeature(String feature, boolean toggle) { this.jacksonConfig.appendJsonFeatureToToggle(Collections.singletonMap(feature, toggle)); From a80ed394092c9cdd76427f60221136db3795649f Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 13:51:01 +0400 Subject: [PATCH 16/18] Sync mvn and gradle tests on YAML --- .../java/com/diffplug/gradle/spotless/YamlExtensionTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java index 82801eb0fd..067c809846 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/YamlExtensionTest.java @@ -73,7 +73,6 @@ void testFormatYaml_WithJackson_multipleDocuments() throws IOException { " yaml {", " target 'src/**/*.yaml'", " jackson()", - " .yamlFeature('MINIMIZE_QUOTES', true)", " }", "}"); setFile("src/main/resources/example.yaml").toResource("yaml/multiple_documents.yaml"); From 6b9b870c8754c4af9967ea094b1049f4dc941d25 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 23:08:33 +0400 Subject: [PATCH 17/18] Rely on generic JsonNode --- .../spotless/glue/yaml/JacksonYamlFormatterFunc.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java index edb350c559..ae6b85530b 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ContainerNode; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; @@ -60,13 +61,11 @@ protected JsonFactory makeJsonFactory() { @Override protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException { - //if (true) - // throw new IllegalArgumentException("input = \r\n" + input); try { // https://stackoverflow.com/questions/25222327/deserialize-pojos-from-multiple-yaml-documents-in-a-single-file-in-jackson // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-375328648 JsonParser yamlParser = objectMapper.getFactory().createParser(input); - List documents = objectMapper.readValues(yamlParser, ContainerNode.class).readAll(); + List documents = objectMapper.readValues(yamlParser, JsonNode.class).readAll(); // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-554265055 // https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-554265055 From 6b6e854e19b0969d23918ae9bd9ec705f25fc46d Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 18 Jan 2023 23:20:27 +0400 Subject: [PATCH 18/18] Fix style --- .../diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java index ae6b85530b..89304d8d0a 100644 --- a/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java @@ -24,7 +24,6 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ContainerNode; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fasterxml.jackson.dataformat.yaml.YAMLFactoryBuilder; import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;