From d3052d3e8193d0aa9421a7b1e25b35062725c862 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Tue, 10 Jan 2023 09:44:56 +0400 Subject: [PATCH 01/11] Base implementation --- .../spotless/yaml/YamlJacksonStep.java | 147 ++++++++++++++++++ .../spotless/maven/yaml/JacksonYaml.java | 46 ++++++ .../diffplug/spotless/maven/yaml/Yaml.java | 41 +++++ .../yaml/separator_comments.clean.yaml | 8 + .../resources/yaml/separator_comments.yaml | 8 + 5 files changed, 250 insertions(+) create mode 100644 lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Yaml.java create mode 100644 testlib/src/main/resources/yaml/separator_comments.clean.yaml create mode 100644 testlib/src/main/resources/yaml/separator_comments.yaml diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java new file mode 100644 index 0000000000..6783b9a976 --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java @@ -0,0 +1,147 @@ +/* + * Copyright 2021 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.io.IOException; +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +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; + +/** + * Simple YAML formatter which reformats the file according to Jackson YAMLFactory. + */ +public final class YamlJacksonStep { + private static final String MAVEN_COORDINATE = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:"; + private static final String DEFAULT_VERSION = "2.13.4"; + + public static String defaultVersion() { + return DEFAULT_VERSION; + } + + public static FormatterStep create(List enabledFeatures, + List disabledFeatures, + String jacksonVersion, + Provisioner provisioner) { + Objects.requireNonNull(provisioner, "provisioner cannot be null"); + return FormatterStep.createLazy("yaml", + () -> new State(enabledFeatures, disabledFeatures, jacksonVersion, provisioner), + State::toFormatter); + } + + public static FormatterStep create(Provisioner provisioner) { + return create(Arrays.asList("INDENT_OUTPUT"), Arrays.asList(), 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 JarState jarState; + + private State(List enabledFeatures, + List disabledFeatures, + String jacksonVersion, + Provisioner provisioner) throws IOException { + this.enabledFeatures = enabledFeatures; + this.disabledFeatures = disabledFeatures; + + this.jarState = JarState.from(MAVEN_COORDINATE + jacksonVersion, provisioner); + } + + FormatterFunc toFormatter() { + Class jsonFactoryClass; + Class yamlFactoryClass; + Class objectMapperClass; + + Class serializationFeatureClass; + Method enableFeature; + Method disableFeature; + + Method stringToObject; + Method objectToString; + try { + ClassLoader classLoader = jarState.getClassLoader(); + jsonFactoryClass = classLoader.loadClass("com.fasterxml.jackson.core.JsonFactory"); + yamlFactoryClass = classLoader.loadClass("com.fasterxml.jackson.dataformat.yaml.YAMLFactory"); + + objectMapperClass = classLoader.loadClass("com.fasterxml.jackson.databind.ObjectMapper"); + + // Configure the ObjectMapper + // https://github.com/FasterXML/jackson-databind#commonly-used-features + { + serializationFeatureClass = + classLoader.loadClass("com.fasterxml.jackson.databind.SerializationFeature"); + enableFeature = objectMapperClass.getMethod("enable", serializationFeatureClass); + disableFeature = objectMapperClass.getMethod("disable", serializationFeatureClass); + } + + stringToObject = objectMapperClass.getMethod("readValue", String.class, Class.class); + objectToString = objectMapperClass.getMethod("writeValueAsString", Object.class); + } catch (ClassNotFoundException | NoSuchMethodException e) { + throw new IllegalStateException("There was a problem preparing org.json dependencies", e); + } + + return s -> { + if (s.isEmpty()) { + return s; + } + + Object yamlFactory = yamlFactoryClass.getConstructor().newInstance(); + Object objectMapper = objectMapperClass.getConstructor(jsonFactoryClass).newInstance(yamlFactory); + + for (String feature : enabledFeatures) { + // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection + Object indentOutput = Enum.valueOf(serializationFeatureClass.asSubclass(Enum.class), feature); + + enableFeature.invoke(objectMapper, indentOutput); + } + + for (String feature : disabledFeatures) { + // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection + Object indentOutput = Enum.valueOf(serializationFeatureClass.asSubclass(Enum.class), feature); + + disableFeature.invoke(objectMapper, indentOutput); + } + + return format(objectMapper, stringToObject, objectToString, s); + }; + } + + private String format(Object objectMapper, Method stringToObject, Method objectToString, String s) + throws IllegalAccessException, IllegalArgumentException { + try { + Object parsed = stringToObject.invoke(s, Object.class); + return (String) objectToString.invoke(objectMapper, parsed); + } catch (InvocationTargetException ex) { + throw new AssertionError("Unable to format YAML", ex.getCause()); + } + } + } + + private YamlJacksonStep() { + // cannot be directly instantiated + } +} 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..90892f969a --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java @@ -0,0 +1,46 @@ +/* + * 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.Arrays; +import java.util.List; + +import org.apache.maven.plugins.annotations.Parameter; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; +import com.diffplug.spotless.yaml.YamlJacksonStep; + +public class JacksonYaml implements FormatterStepFactory { + + @Parameter + private String version = YamlJacksonStep.defaultVersion(); + + @Parameter + private String[] enabledFeatures = new String[] { "INDENT_OUTPUT" }; + + @Parameter + private String[] disabledFeatures = new String[0]; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { + List enabledFeaturesAsList = Arrays.asList(enabledFeatures); + List disabledFeaturesAsList = Arrays.asList(disabledFeatures); + return YamlJacksonStep + .create(enabledFeaturesAsList, disabledFeaturesAsList, 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 new file mode 100644 index 0000000000..a6ceaaa592 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Yaml.java @@ -0,0 +1,41 @@ +/* + * 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.Set; + +import com.diffplug.spotless.maven.FormatterFactory; + +/** + * A {@link FormatterFactory} implementation that corresponds to {@code ...} configuration element. + */ +public class Yaml extends FormatterFactory { + @Override + public Set defaultIncludes() { + return Collections.emptySet(); + } + + @Override + public String licenseHeaderDelimiter() { + return null; + } + + public void addJackson(JacksonYaml jackson) { + addStepFactory(jackson); + } + +} diff --git a/testlib/src/main/resources/yaml/separator_comments.clean.yaml b/testlib/src/main/resources/yaml/separator_comments.clean.yaml new file mode 100644 index 0000000000..bf46f753c0 --- /dev/null +++ b/testlib/src/main/resources/yaml/separator_comments.clean.yaml @@ -0,0 +1,8 @@ +--- +hr: + - Mark McGwire + # Following node labeled SS + - &SS Sammy Sosa +rbi: + - *SS # Subsequent occurrence + - Ken Griffey \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/separator_comments.yaml b/testlib/src/main/resources/yaml/separator_comments.yaml new file mode 100644 index 0000000000..bf46f753c0 --- /dev/null +++ b/testlib/src/main/resources/yaml/separator_comments.yaml @@ -0,0 +1,8 @@ +--- +hr: + - Mark McGwire + # Following node labeled SS + - &SS Sammy Sosa +rbi: + - *SS # Subsequent occurrence + - Ken Griffey \ No newline at end of file From a89ba3a94d1c05fe4e190d006a2fd4d678f9acb0 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Tue, 10 Jan 2023 10:01:58 +0400 Subject: [PATCH 02/11] Progress with doc and tests --- CHANGES.md | 1 + .../spotless/yaml/YamlJacksonStep.java | 5 +-- plugin-maven/CHANGES.md | 1 + plugin-maven/README.md | 39 ++++++++++++++++++- .../spotless/maven/yaml/JacksonYaml.java | 2 +- .../diffplug/spotless/maven/yaml/Yaml.java | 4 +- .../maven/MavenIntegrationHarness.java | 4 ++ .../spotless/maven/yaml/YamlTest.java | 31 +++++++++++++++ 8 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java diff --git a/CHANGES.md b/CHANGES.md index 9ca16e4dc3..32ef01ad67 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added * Added `skipLinesMatching` option to `licenseHeader` to support formats where license header cannot be immediately added to the top of the file (e.g. xml, sh). ([#1441](https://github.com/diffplug/spotless/pull/1441)). +* Add YAML support through Jackson ([#1478](https://github.com/diffplug/spotless/pull/1478)) ### Fixed * Support `ktlint` 0.48+ new rule disabling syntax ([#1456](https://github.com/diffplug/spotless/pull/1456)) fixes ([#1444](https://github.com/diffplug/spotless/issues/1444)) diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java index 6783b9a976..4e76bb2941 100644 --- a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java +++ b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.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. @@ -92,8 +92,7 @@ FormatterFunc toFormatter() { // Configure the ObjectMapper // https://github.com/FasterXML/jackson-databind#commonly-used-features { - serializationFeatureClass = - classLoader.loadClass("com.fasterxml.jackson.databind.SerializationFeature"); + serializationFeatureClass = classLoader.loadClass("com.fasterxml.jackson.databind.SerializationFeature"); enableFeature = objectMapperClass.getMethod("enable", serializationFeatureClass); disableFeature = objectMapperClass.getMethod("disable", serializationFeatureClass); } diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 984c86d502..6212bf1872 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -5,6 +5,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added * Added `skipLinesMatching` option to `licenseHeader` to support formats where license header cannot be immediately added to the top of the file (e.g. xml, sh). ([#1441](https://github.com/diffplug/spotless/pull/1441)) +* Add YAML support through Jackson ([#1478](https://github.com/diffplug/spotless/pull/1478)) ### Fixed * Support `ktlint` 0.48+ new rule disabling syntax ([#1456](https://github.com/diffplug/spotless/pull/1456)) fixes ([#1444](https://github.com/diffplug/spotless/issues/1444)) ### Changes diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 11f6c35deb..9255594375 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -59,6 +59,7 @@ user@machine repo % mvn spotless:check - [Markdown](#markdown) ([flexmark](#flexmark)) - [Typescript](#typescript) ([tsfmt](#tsfmt), [prettier](#prettier)) - [JSON](#json) + - [YAML](#yaml) - Multiple languages - [Prettier](#prettier) ([plugins](#prettier-plugins), [npm detection](#npm-detection), [`.npmrc` detection](#npmrc-detection)) - [eclipse web tools platform](#eclipse-web-tools-platform) @@ -712,7 +713,7 @@ For details, see the [npm detection](#npm-detection) and [`.npmrc` detection](#n ## JSON -- `com.diffplug.spotless.maven.json.Json` [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/json.java) +- `com.diffplug.spotless.maven.json.Json` [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/json/Json.java) ```xml @@ -759,6 +760,42 @@ for details. + +## YAML + +- `com.diffplug.spotless.maven.FormatterFactory.addStepFactory(FormatterStepFactory)` [code](https://github.com/diffplug/spotless/blob/main/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Yaml.java) + +```xml + + + + **/*.yaml + **/*.yml + + + + + +``` + +### jackson + +Uses Jackson and YAMLFactory to pretty print objects: + +```xml + + 2.13.4 + + INDENT_OUTPUT + + + DEFAULT_HAS_TO_DISABLED_FEATURE + + +``` + + + ## Prettier [homepage](https://prettier.io/). [changelog](https://github.com/prettier/prettier/blob/master/CHANGELOG.md). [official plugins](https://prettier.io/docs/en/plugins.html#official-plugins). [community plugins](https://prettier.io/docs/en/plugins.html#community-plugins). Prettier is a formatter that can format almost every anything - JavaScript, JSX, Angular, Vue, Flow, TypeScript, CSS, Less, SCSS, HTML, JSON, GraphQL, Markdown (including GFM and MDX), and YAML. It can format even more [using plugins](https://prettier.io/docs/en/plugins.html) (PHP, Ruby, Swift, XML, Apex, Elm, Java (!!), Kotlin, pgSQL, .properties, solidity, svelte, toml, shellscript, ...). 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 90892f969a..86b52aac7d 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 @@ -31,7 +31,7 @@ public class JacksonYaml implements FormatterStepFactory { private String version = YamlJacksonStep.defaultVersion(); @Parameter - private String[] enabledFeatures = new String[] { "INDENT_OUTPUT" }; + private String[] enabledFeatures = new String[]{"INDENT_OUTPUT"}; @Parameter private String[] disabledFeatures = new String[0]; 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 a6ceaaa592..20e609ceb4 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 @@ -15,9 +15,9 @@ */ package com.diffplug.spotless.maven.yaml; -import java.util.Collections; import java.util.Set; +import com.diffplug.common.collect.Sets; import com.diffplug.spotless.maven.FormatterFactory; /** @@ -26,7 +26,7 @@ public class Yaml extends FormatterFactory { @Override public Set defaultIncludes() { - return Collections.emptySet(); + return Sets.newHashSet("**/*.yaml", "**/*.yml"); } @Override diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java index 9e9495da65..5dbd3e0075 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java @@ -160,6 +160,10 @@ protected void writePomWithJsonSteps(String... steps) throws IOException { writePom(groupWithSteps("json", including("**/*.json"), steps)); } + protected void writePomWithYamlSteps(String... steps) throws IOException { + writePom(groupWithSteps("yaml", steps)); + } + protected void writePom(String... configuration) throws IOException { writePom(null, configuration, null); } 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 new file mode 100644 index 0000000000..8b9bab6cbb --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/yaml/YamlTest.java @@ -0,0 +1,31 @@ +/* + * 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 org.junit.jupiter.api.Test; + +import com.diffplug.spotless.maven.MavenIntegrationHarness; + +public class YamlTest extends MavenIntegrationHarness { + @Test + public void testFormatJson_WithSimple_defaultConfig() throws Exception { + writePomWithJsonSteps(""); + + setFile("yaml_test.json").toResource("yaml/separator_comments.yaml"); + mavenRunner().withArguments("spotless:apply").runNoError().error(); + assertFile("yaml_test.json").sameAsResource("yaml/separator_comments.clean.yaml"); + } +} From 3244f2defe92773733c7d600c0c9f4440506de65 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Tue, 10 Jan 2023 10:05:31 +0400 Subject: [PATCH 03/11] Add unit-tests --- .../spotless/maven/yaml/YamlTest.java | 20 ++++++++++++++++++- .../yaml/array_with_bracket.clean.yaml | 8 ++++++++ .../resources/yaml/array_with_bracket.yaml | 5 +++++ .../yaml/multiple_document.clean.yaml | 8 ++++++++ .../resources/yaml/multiple_document.yaml | 10 ++++++++++ .../resources/yaml/separator_comments.yaml | 1 + 6 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 testlib/src/main/resources/yaml/array_with_bracket.clean.yaml create mode 100644 testlib/src/main/resources/yaml/array_with_bracket.yaml create mode 100644 testlib/src/main/resources/yaml/multiple_document.clean.yaml create mode 100644 testlib/src/main/resources/yaml/multiple_document.yaml 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 8b9bab6cbb..b2168ff05f 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 @@ -21,11 +21,29 @@ public class YamlTest extends MavenIntegrationHarness { @Test - public void testFormatJson_WithSimple_defaultConfig() throws Exception { + public void testFormatYaml_WithJackson_defaultConfig_separatorComments() throws Exception { writePomWithJsonSteps(""); setFile("yaml_test.json").toResource("yaml/separator_comments.yaml"); mavenRunner().withArguments("spotless:apply").runNoError().error(); assertFile("yaml_test.json").sameAsResource("yaml/separator_comments.clean.yaml"); } + + @Test + public void testFormatYaml_WithJackson_defaultConfig_arrayBrackets() throws Exception { + writePomWithJsonSteps(""); + + setFile("yaml_test.json").toResource("yaml/array_with_bracket.yaml"); + mavenRunner().withArguments("spotless:apply").runNoError().error(); + assertFile("yaml_test.json").sameAsResource("yaml/array_with_bracket.clean.yaml"); + } + + @Test + public void testFormatYaml_WithJackson_defaultConfig_multipleComments() throws Exception { + writePomWithJsonSteps(""); + + setFile("yaml_test.json").toResource("yaml/multiple_documents.yaml"); + mavenRunner().withArguments("spotless:apply").runNoError().error(); + assertFile("yaml_test.json").sameAsResource("yaml/multiple_documents.clean.yaml"); + } } diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml new file mode 100644 index 0000000000..bf46f753c0 --- /dev/null +++ b/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml @@ -0,0 +1,8 @@ +--- +hr: + - Mark McGwire + # Following node labeled SS + - &SS Sammy Sosa +rbi: + - *SS # Subsequent occurrence + - Ken Griffey \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/array_with_bracket.yaml b/testlib/src/main/resources/yaml/array_with_bracket.yaml new file mode 100644 index 0000000000..c83e381e6b --- /dev/null +++ b/testlib/src/main/resources/yaml/array_with_bracket.yaml @@ -0,0 +1,5 @@ +hr: [Mark McGwire, Sammy Sosa] + + + +rbi: [Sammy Sosa, Ken Griffey] \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/multiple_document.clean.yaml b/testlib/src/main/resources/yaml/multiple_document.clean.yaml new file mode 100644 index 0000000000..bf46f753c0 --- /dev/null +++ b/testlib/src/main/resources/yaml/multiple_document.clean.yaml @@ -0,0 +1,8 @@ +--- +hr: + - Mark McGwire + # Following node labeled SS + - &SS Sammy Sosa +rbi: + - *SS # Subsequent occurrence + - Ken Griffey \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/multiple_document.yaml b/testlib/src/main/resources/yaml/multiple_document.yaml new file mode 100644 index 0000000000..51f14a5862 --- /dev/null +++ b/testlib/src/main/resources/yaml/multiple_document.yaml @@ -0,0 +1,10 @@ +document: this is document 1 +--- + +document: this is document 2 + + +--- + + +document: this is document 3 \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/separator_comments.yaml b/testlib/src/main/resources/yaml/separator_comments.yaml index bf46f753c0..0213e66406 100644 --- a/testlib/src/main/resources/yaml/separator_comments.yaml +++ b/testlib/src/main/resources/yaml/separator_comments.yaml @@ -1,3 +1,4 @@ + --- hr: - Mark McGwire From 43078663dbf2b7cf1fcdf55f1c25b41d272684ad Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Tue, 10 Jan 2023 10:06:36 +0400 Subject: [PATCH 04/11] Improve testcases --- .../main/resources/yaml/array_with_bracket.clean.yaml | 10 ++-------- .../src/main/resources/yaml/array_with_bracket.yaml | 4 ++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml index bf46f753c0..8e9d80065e 100644 --- a/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml +++ b/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml @@ -1,8 +1,2 @@ ---- -hr: - - Mark McGwire - # Following node labeled SS - - &SS Sammy Sosa -rbi: - - *SS # Subsequent occurrence - - Ken Griffey \ No newline at end of file +episodes: [1, 2, 3, 4, 5, 6, 7] +best-jedi: {name: Obi-Wan, side: light} \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/array_with_bracket.yaml b/testlib/src/main/resources/yaml/array_with_bracket.yaml index c83e381e6b..e28373163d 100644 --- a/testlib/src/main/resources/yaml/array_with_bracket.yaml +++ b/testlib/src/main/resources/yaml/array_with_bracket.yaml @@ -1,5 +1,5 @@ -hr: [Mark McGwire, Sammy Sosa] +episodes: [1, 2, 3, 4, 5, 6, 7] -rbi: [Sammy Sosa, Ken Griffey] \ No newline at end of file +best-jedi: {name: Obi-Wan, side: light} \ No newline at end of file From 4438d1845f94cfa25f01576f1f9f60850de4690e Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Tue, 10 Jan 2023 21:43:13 +0400 Subject: [PATCH 05/11] Small fixes --- plugin-maven/README.md | 11 +++++----- .../spotless/maven/AbstractSpotlessMojo.java | 12 +++++++++-- .../yaml/{JacksonYaml.java => Jackson.java} | 2 +- .../diffplug/spotless/maven/yaml/Yaml.java | 6 +++--- .../maven/MavenIntegrationHarness.java | 2 +- .../spotless/maven/json/JsonTest.java | 4 ++-- .../spotless/maven/yaml/YamlTest.java | 20 +++++++++---------- .../yaml/multiple_document.clean.yaml | 8 -------- .../yaml/multiple_documents.clean.yaml | 8 ++++++++ ..._document.yaml => multiple_documents.yaml} | 0 .../yaml/separator_comments.clean.yaml | 1 + 11 files changed, 41 insertions(+), 33 deletions(-) rename plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/{JacksonYaml.java => Jackson.java} (96%) delete mode 100644 testlib/src/main/resources/yaml/multiple_document.clean.yaml create mode 100644 testlib/src/main/resources/yaml/multiple_documents.clean.yaml rename testlib/src/main/resources/yaml/{multiple_document.yaml => multiple_documents.yaml} (100%) diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 9255594375..0fe8bb52b4 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -768,9 +768,8 @@ for details. ```xml - - **/*.yaml - **/*.yml + + src/**/*.yaml @@ -785,11 +784,11 @@ Uses Jackson and YAMLFactory to pretty print objects: ```xml 2.13.4 - + INDENT_OUTPUT - - DEFAULT_HAS_TO_DISABLED_FEATURE + + DEFAULT_HAS_NO_DISABLED_FEATURE ``` diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index e4fdc7dcd0..31fd5fd5e3 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.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. @@ -64,6 +64,7 @@ import com.diffplug.spotless.maven.incremental.UpToDateChecker; import com.diffplug.spotless.maven.incremental.UpToDateChecking; import com.diffplug.spotless.maven.java.Java; +import com.diffplug.spotless.maven.json.Json; import com.diffplug.spotless.maven.kotlin.Kotlin; import com.diffplug.spotless.maven.markdown.Markdown; import com.diffplug.spotless.maven.pom.Pom; @@ -71,6 +72,7 @@ import com.diffplug.spotless.maven.scala.Scala; import com.diffplug.spotless.maven.sql.Sql; import com.diffplug.spotless.maven.typescript.Typescript; +import com.diffplug.spotless.maven.yaml.Yaml; public abstract class AbstractSpotlessMojo extends AbstractMojo { private static final String DEFAULT_INDEX_FILE_NAME = "spotless-index"; @@ -167,6 +169,12 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo { @Parameter private Markdown markdown; + @Parameter + private Json json; + + @Parameter + private Yaml yaml; + @Parameter(property = "spotlessFiles") private String filePatterns; @@ -331,7 +339,7 @@ private FileLocator getFileLocator() { } private List getFormatterFactories() { - return Stream.concat(formats.stream(), Stream.of(groovy, java, scala, kotlin, cpp, typescript, antlr4, pom, sql, python, markdown)) + return Stream.concat(formats.stream(), Stream.of(groovy, java, scala, kotlin, cpp, typescript, antlr4, pom, sql, python, markdown, json, yaml)) .filter(Objects::nonNull) .collect(toList()); } 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/Jackson.java similarity index 96% rename from plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/JacksonYaml.java rename to plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Jackson.java index 86b52aac7d..2bc7617a38 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/Jackson.java @@ -25,7 +25,7 @@ import com.diffplug.spotless.maven.FormatterStepFactory; import com.diffplug.spotless.yaml.YamlJacksonStep; -public class JacksonYaml implements FormatterStepFactory { +public class Jackson implements FormatterStepFactory { @Parameter private String version = YamlJacksonStep.defaultVersion(); 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 20e609ceb4..6cba1b2ebd 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 @@ -15,9 +15,9 @@ */ package com.diffplug.spotless.maven.yaml; +import java.util.Collections; import java.util.Set; -import com.diffplug.common.collect.Sets; import com.diffplug.spotless.maven.FormatterFactory; /** @@ -26,7 +26,7 @@ public class Yaml extends FormatterFactory { @Override public Set defaultIncludes() { - return Sets.newHashSet("**/*.yaml", "**/*.yml"); + return Collections.emptySet(); } @Override @@ -34,7 +34,7 @@ public String licenseHeaderDelimiter() { return null; } - public void addJackson(JacksonYaml jackson) { + public void addJackson(Jackson jackson) { addStepFactory(jackson); } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java index 5dbd3e0075..a008a8bf4f 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenIntegrationHarness.java @@ -161,7 +161,7 @@ protected void writePomWithJsonSteps(String... steps) throws IOException { } protected void writePomWithYamlSteps(String... steps) throws IOException { - writePom(groupWithSteps("yaml", steps)); + writePom(groupWithSteps("yaml", including("**/*.yaml"), steps)); } protected void writePom(String... configuration) throws IOException { 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 fe6560cbec..f63dc708e9 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 @@ -22,7 +22,7 @@ public class JsonTest extends MavenIntegrationHarness { @Test public void testFormatJson_WithSimple_defaultConfig() throws Exception { - writePomWithJsonSteps(""); + writePomWithJsonSteps(""); setFile("json_test.json").toResource("json/sortByKeysBefore.json"); mavenRunner().withArguments("spotless:apply").runNoError().error(); @@ -31,7 +31,7 @@ public void testFormatJson_WithSimple_defaultConfig() throws Exception { @Test public void testFormatJson_WithGson_defaultConfig() throws Exception { - writePomWithJsonSteps(""); + writePomWithJsonSteps(""); setFile("json_test.json").toResource("json/sortByKeysBefore.json"); mavenRunner().withArguments("spotless:apply").runNoError().error(); 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 b2168ff05f..4614b42f22 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 @@ -22,28 +22,28 @@ public class YamlTest extends MavenIntegrationHarness { @Test public void testFormatYaml_WithJackson_defaultConfig_separatorComments() throws Exception { - writePomWithJsonSteps(""); + writePomWithYamlSteps(""); - setFile("yaml_test.json").toResource("yaml/separator_comments.yaml"); + setFile("yaml_test.yaml").toResource("yaml/separator_comments.yaml"); mavenRunner().withArguments("spotless:apply").runNoError().error(); - assertFile("yaml_test.json").sameAsResource("yaml/separator_comments.clean.yaml"); + assertFile("yaml_test.yaml").sameAsResource("yaml/separator_comments.clean.yaml"); } @Test public void testFormatYaml_WithJackson_defaultConfig_arrayBrackets() throws Exception { - writePomWithJsonSteps(""); + writePomWithYamlSteps(""); - setFile("yaml_test.json").toResource("yaml/array_with_bracket.yaml"); + setFile("yaml_test.yaml").toResource("yaml/array_with_bracket.yaml"); mavenRunner().withArguments("spotless:apply").runNoError().error(); - assertFile("yaml_test.json").sameAsResource("yaml/array_with_bracket.clean.yaml"); + assertFile("yaml_test.yaml").sameAsResource("yaml/array_with_bracket.clean.yaml"); } @Test - public void testFormatYaml_WithJackson_defaultConfig_multipleComments() throws Exception { - writePomWithJsonSteps(""); + public void testFormatYaml_WithJackson_defaultConfig_multipleDocuments() throws Exception { + writePomWithYamlSteps(""); - setFile("yaml_test.json").toResource("yaml/multiple_documents.yaml"); + setFile("yaml_test.yaml").toResource("yaml/multiple_documents.yaml"); mavenRunner().withArguments("spotless:apply").runNoError().error(); - assertFile("yaml_test.json").sameAsResource("yaml/multiple_documents.clean.yaml"); + assertFile("yaml_test.yaml").sameAsResource("yaml/multiple_documents.clean.yaml"); } } diff --git a/testlib/src/main/resources/yaml/multiple_document.clean.yaml b/testlib/src/main/resources/yaml/multiple_document.clean.yaml deleted file mode 100644 index bf46f753c0..0000000000 --- a/testlib/src/main/resources/yaml/multiple_document.clean.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -hr: - - Mark McGwire - # Following node labeled SS - - &SS Sammy Sosa -rbi: - - *SS # Subsequent occurrence - - Ken Griffey \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/multiple_documents.clean.yaml b/testlib/src/main/resources/yaml/multiple_documents.clean.yaml new file mode 100644 index 0000000000..612497c0ab --- /dev/null +++ b/testlib/src/main/resources/yaml/multiple_documents.clean.yaml @@ -0,0 +1,8 @@ +document: this is document 1 +--- + +document: this is document 2 + +--- + +document: this is document 3 \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/multiple_document.yaml b/testlib/src/main/resources/yaml/multiple_documents.yaml similarity index 100% rename from testlib/src/main/resources/yaml/multiple_document.yaml rename to testlib/src/main/resources/yaml/multiple_documents.yaml diff --git a/testlib/src/main/resources/yaml/separator_comments.clean.yaml b/testlib/src/main/resources/yaml/separator_comments.clean.yaml index bf46f753c0..98160e910f 100644 --- a/testlib/src/main/resources/yaml/separator_comments.clean.yaml +++ b/testlib/src/main/resources/yaml/separator_comments.clean.yaml @@ -1,4 +1,5 @@ --- + hr: - Mark McGwire # Following node labeled SS From dcf727c4ceb1c1c1cff88d3dc4e5c38a1f6ab99e Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 11 Jan 2023 08:46:12 +0400 Subject: [PATCH 06/11] Add not trivial json tests --- .../spotless/maven/json/JsonTest.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) 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 f63dc708e9..45607807b1 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 @@ -21,7 +21,7 @@ public class JsonTest extends MavenIntegrationHarness { @Test - public void testFormatJson_WithSimple_defaultConfig() throws Exception { + public void testFormatJson_WithSimple_defaultConfig_sortByKeys() throws Exception { writePomWithJsonSteps(""); setFile("json_test.json").toResource("json/sortByKeysBefore.json"); @@ -30,11 +30,30 @@ public void testFormatJson_WithSimple_defaultConfig() throws Exception { } @Test - public void testFormatJson_WithGson_defaultConfig() throws Exception { + public void testFormatJson_WithSimple_defaultConfig_nestedObject() throws Exception { + writePomWithJsonSteps(""); + + setFile("json_test.json").toResource("json/nestedObjectBefore.json"); + mavenRunner().withArguments("spotless:apply").runNoError().error(); + assertFile("json_test.json").sameAsResource("json/nestedObjectAfter.json"); + } + + @Test + public void testFormatJson_WithGson_defaultConfig_sortByKeys() throws Exception { writePomWithJsonSteps(""); setFile("json_test.json").toResource("json/sortByKeysBefore.json"); mavenRunner().withArguments("spotless:apply").runNoError().error(); assertFile("json_test.json").sameAsResource("json/sortByKeysAfterDisabled.json"); } + + @Test + public void testFormatJson_WithGson_sortByKeys() throws Exception { + writePomWithJsonSteps("true"); + + setFile("json_test.json").toResource("json/sortByKeysBefore.json"); + mavenRunner().withArguments("spotless:apply").runNoError().error(); + assertFile("json_test.json").sameAsResource("json/sortByKeysAfter.json"); + } + } From 5041562dfa5e24bbc8f6cb9d3d85008d8e8e5ad1 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 11 Jan 2023 14:48:22 +0400 Subject: [PATCH 07/11] Fix reflection on stringToObject --- .../main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java index 4e76bb2941..b29c6ad267 100644 --- a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java +++ b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java @@ -132,7 +132,7 @@ FormatterFunc toFormatter() { private String format(Object objectMapper, Method stringToObject, Method objectToString, String s) throws IllegalAccessException, IllegalArgumentException { try { - Object parsed = stringToObject.invoke(s, Object.class); + Object parsed = stringToObject.invoke(objectMapper, s, Object.class); return (String) objectToString.invoke(objectMapper, parsed); } catch (InvocationTargetException ex) { throw new AssertionError("Unable to format YAML", ex.getCause()); From dcb82ae3d82437252cf93d70e3ccb8c7016b467c Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 11 Jan 2023 15:55:48 +0400 Subject: [PATCH 08/11] Fix cleaned YAML given limitations of Jackson --- .../resources/yaml/array_with_bracket.clean.yaml | 14 ++++++++++++-- .../resources/yaml/multiple_documents.clean.yaml | 4 ++-- .../resources/yaml/separator_comments.clean.yaml | 6 ++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml index 8e9d80065e..88fc8fd541 100644 --- a/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml +++ b/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml @@ -1,2 +1,12 @@ -episodes: [1, 2, 3, 4, 5, 6, 7] -best-jedi: {name: Obi-Wan, side: light} \ No newline at end of file +--- +episodes: +- 1 +- 2 +- 3 +- 4 +- 5 +- 6 +- 7 +best-jedi: + name: Obi-Wan + side: light \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/multiple_documents.clean.yaml b/testlib/src/main/resources/yaml/multiple_documents.clean.yaml index 612497c0ab..45e0b0916b 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 1 +--- document: this is document 2 --- - document: this is document 3 \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/separator_comments.clean.yaml b/testlib/src/main/resources/yaml/separator_comments.clean.yaml index 98160e910f..7dac8a279f 100644 --- a/testlib/src/main/resources/yaml/separator_comments.clean.yaml +++ b/testlib/src/main/resources/yaml/separator_comments.clean.yaml @@ -1,9 +1,7 @@ --- - hr: - Mark McGwire - # Following node labeled SS - - &SS Sammy Sosa + - Sammy Sosa rbi: - - *SS # Subsequent occurrence + - Sammy Sosa - Ken Griffey \ No newline at end of file From fb3bb169b6d0df3322b30fa585511bb952a2163b Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 11 Jan 2023 16:42:03 +0400 Subject: [PATCH 09/11] Fix cleaned YAMLs --- .../src/main/resources/yaml/array_with_bracket.clean.yaml | 4 ++-- .../src/main/resources/yaml/separator_comments.clean.yaml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml b/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml index 88fc8fd541..c6f891b9de 100644 --- a/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml +++ b/testlib/src/main/resources/yaml/array_with_bracket.clean.yaml @@ -8,5 +8,5 @@ episodes: - 6 - 7 best-jedi: - name: Obi-Wan - side: light \ No newline at end of file + name: "Obi-Wan" + side: "light" \ No newline at end of file diff --git a/testlib/src/main/resources/yaml/separator_comments.clean.yaml b/testlib/src/main/resources/yaml/separator_comments.clean.yaml index 7dac8a279f..35bb8717dd 100644 --- a/testlib/src/main/resources/yaml/separator_comments.clean.yaml +++ b/testlib/src/main/resources/yaml/separator_comments.clean.yaml @@ -1,7 +1,7 @@ --- hr: - - Mark McGwire - - Sammy Sosa +- "Mark McGwire" +- "Sammy Sosa" rbi: - - Sammy Sosa - - Ken Griffey \ No newline at end of file +- "SS" +- "Ken Griffey" \ No newline at end of file From 13d9d3cd19eaa8812191c44db045aee754df569b Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Thu, 12 Jan 2023 11:06:03 +0400 Subject: [PATCH 10/11] Fix YAML and JSON tests --- .gitignore | 3 + .java-version | 1 - lib/build.gradle | 6 +- .../glue/yaml/YamlJacksonFormatterFunc.java | 99 +++++++++++++++++++ .../spotless/yaml/YamlJacksonStep.java | 31 ++++-- .../spotless/yaml/YamlJacksonV2Step.java | 77 +++++++++++++++ .../diffplug/spotless/maven/yaml/Jackson.java | 3 +- .../spotless/maven/json/JsonTest.java | 26 ++++- .../spotless/maven/yaml/YamlTest.java | 18 +++- .../json/sortByKeysAfterDisabled_Simple.json | 19 ++++ .../multiple_documents.clean.jackson.yaml | 2 + 11 files changed, 263 insertions(+), 22 deletions(-) delete mode 100644 .java-version create mode 100644 lib/src/jackson/java/com/diffplug/spotless/glue/yaml/YamlJacksonFormatterFunc.java create mode 100644 lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonV2Step.java create mode 100644 testlib/src/main/resources/json/sortByKeysAfterDisabled_Simple.json create mode 100644 testlib/src/main/resources/yaml/multiple_documents.clean.jackson.yaml diff --git a/.gitignore b/.gitignore index 1a95765d37..138bb77159 100644 --- a/.gitignore +++ b/.gitignore @@ -121,3 +121,6 @@ nbdist/ nbactions.xml nb-configuration.xml .nb-gradle/ + +# MacOS jenv +.java-version diff --git a/.java-version b/.java-version deleted file mode 100644 index 2dbc24b32d..0000000000 --- a/.java-version +++ /dev/null @@ -1 +0,0 @@ -11.0 diff --git a/lib/build.gradle b/lib/build.gradle index 115d27195f..0cf07f9531 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -14,7 +14,8 @@ def NEEDS_GLUE = [ 'ktlint', 'flexmark', 'diktat', - 'scalafmt' + 'scalafmt', + 'jackson' ] for (glue in NEEDS_GLUE) { sourceSets.register(glue) { @@ -55,6 +56,9 @@ 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.dataformat:jackson-dataformat-yaml:2.13.4' + String VER_KTFMT = '0.42' ktfmtCompileOnly "com.facebook:ktfmt:$VER_KTFMT" String VER_KTLINT_GOOGLE_JAVA_FORMAT = '1.7' // for JDK 8 compatibility 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 new file mode 100644 index 0000000000..604ad048c8 --- /dev/null +++ b/lib/src/jackson/java/com/diffplug/spotless/glue/yaml/YamlJacksonFormatterFunc.java @@ -0,0 +1,99 @@ +/* + * 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 java.util.List; + +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; + +public class YamlJacksonFormatterFunc implements FormatterFunc { + private List enabledFeatures; + private List disabledFeatures; + + // private static final Logger logger = LoggerFactory.getLogger(YamlJacksonFormatterFunc.class); + + public YamlJacksonFormatterFunc(List enabledFeatures, List disabledFeatures) { + this.enabledFeatures = enabledFeatures; + this.disabledFeatures = disabledFeatures; + } + + @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); + } + } + + // Spotbugs + private static class ObjectNodeTypeReference extends TypeReference {} +} diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java index b29c6ad267..c0c660694b 100644 --- a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java +++ b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java @@ -31,9 +31,10 @@ /** * 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 final class YamlJacksonStep { - private static final String MAVEN_COORDINATE = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:"; - private static final String DEFAULT_VERSION = "2.13.4"; + static final String MAVEN_COORDINATE = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:"; + static final String DEFAULT_VERSION = "2.13.4"; public static String defaultVersion() { return DEFAULT_VERSION; @@ -80,8 +81,8 @@ FormatterFunc toFormatter() { Method enableFeature; Method disableFeature; - Method stringToObject; - Method objectToString; + Method stringToNode; + Method nodeToString; try { ClassLoader classLoader = jarState.getClassLoader(); jsonFactoryClass = classLoader.loadClass("com.fasterxml.jackson.core.JsonFactory"); @@ -97,8 +98,18 @@ FormatterFunc toFormatter() { disableFeature = objectMapperClass.getMethod("disable", serializationFeatureClass); } - stringToObject = objectMapperClass.getMethod("readValue", String.class, Class.class); - objectToString = objectMapperClass.getMethod("writeValueAsString", Object.class); + // https://stackoverflow.com/questions/25222327/deserialize-pojos-from-multiple-yaml-documents-in-a-single-file-in-jackson + // List docs = mapper + // .readValues(yamlParser, new TypeReference {}) + // .readAll(); + + Class jsonNodeClass = classLoader.loadClass("com.fasterxml.jackson.databind.JsonNode"); + + // This will transit with a JsonNode + // A JsonNode may keep the comments from the input node + stringToNode = objectMapperClass.getMethod("readTree", String.class); + // Not 'toPrettyString' as one could require no INDENT_OUTPUT + nodeToString = jsonNodeClass.getMethod("toPrettyString"); } catch (ClassNotFoundException | NoSuchMethodException e) { throw new IllegalStateException("There was a problem preparing org.json dependencies", e); } @@ -125,15 +136,15 @@ FormatterFunc toFormatter() { disableFeature.invoke(objectMapper, indentOutput); } - return format(objectMapper, stringToObject, objectToString, s); + return format(objectMapper, stringToNode, nodeToString, s); }; } - private String format(Object objectMapper, Method stringToObject, Method objectToString, String s) + private String format(Object objectMapper, Method stringToNode, Method nodeToString, String s) throws IllegalAccessException, IllegalArgumentException { try { - Object parsed = stringToObject.invoke(objectMapper, s, Object.class); - return (String) objectToString.invoke(objectMapper, parsed); + Object node = stringToNode.invoke(objectMapper, s); + return (String) nodeToString.invoke(node); } catch (InvocationTargetException ex) { throw new AssertionError("Unable to format YAML", ex.getCause()); } diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonV2Step.java b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonV2Step.java new file mode 100644 index 0000000000..f9b1d6b7dc --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonV2Step.java @@ -0,0 +1,77 @@ +/* + * 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.yaml; + +import java.io.IOException; +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; + +public class YamlJacksonV2Step { + private YamlJacksonV2Step() {} + + public static String defaultVersion() { + return YamlJacksonStep.DEFAULT_VERSION; + } + + public static FormatterStep create(List enabledFeatures, + List disabledFeatures, + String jacksonVersion, + Provisioner provisioner) { + Objects.requireNonNull(provisioner, "provisioner cannot be null"); + return FormatterStep.createLazy("yaml", + () -> new State(enabledFeatures, disabledFeatures, jacksonVersion, provisioner), + State::toFormatter); + } + + public static FormatterStep create(Provisioner provisioner) { + return create(Arrays.asList("INDENT_OUTPUT"), Arrays.asList(), 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 JarState jarState; + + private State(List enabledFeatures, + List disabledFeatures, + String jacksonVersion, + Provisioner provisioner) throws IOException { + this.enabledFeatures = enabledFeatures; + this.disabledFeatures = disabledFeatures; + + this.jarState = JarState.from(YamlJacksonStep.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); + } + } +} 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/yaml/Jackson.java index 2bc7617a38..28fdf5809c 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Jackson.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Jackson.java @@ -24,6 +24,7 @@ import com.diffplug.spotless.maven.FormatterStepConfig; import com.diffplug.spotless.maven.FormatterStepFactory; import com.diffplug.spotless.yaml.YamlJacksonStep; +import com.diffplug.spotless.yaml.YamlJacksonV2Step; public class Jackson implements FormatterStepFactory { @@ -40,7 +41,7 @@ public class Jackson implements FormatterStepFactory { public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { List enabledFeaturesAsList = Arrays.asList(enabledFeatures); List disabledFeaturesAsList = Arrays.asList(disabledFeatures); - return YamlJacksonStep + return YamlJacksonV2Step .create(enabledFeaturesAsList, disabledFeaturesAsList, 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 45607807b1..e492109faa 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 @@ -16,17 +16,21 @@ package com.diffplug.spotless.maven.json; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.diffplug.spotless.maven.MavenIntegrationHarness; public class JsonTest extends MavenIntegrationHarness { + private static final Logger LOGGER = LoggerFactory.getLogger(JsonTest.class); + @Test public void testFormatJson_WithSimple_defaultConfig_sortByKeys() throws Exception { writePomWithJsonSteps(""); setFile("json_test.json").toResource("json/sortByKeysBefore.json"); - mavenRunner().withArguments("spotless:apply").runNoError().error(); - assertFile("json_test.json").sameAsResource("json/sortByKeysAfterDisabled.json"); + mavenRunner().withArguments("spotless:apply").runNoError(); + assertFile("json_test.json").sameAsResource("json/sortByKeysAfterDisabled_Simple.json"); } @Test @@ -34,7 +38,7 @@ public void testFormatJson_WithSimple_defaultConfig_nestedObject() throws Except writePomWithJsonSteps(""); setFile("json_test.json").toResource("json/nestedObjectBefore.json"); - mavenRunner().withArguments("spotless:apply").runNoError().error(); + mavenRunner().withArguments("spotless:apply").runNoError(); assertFile("json_test.json").sameAsResource("json/nestedObjectAfter.json"); } @@ -43,7 +47,7 @@ public void testFormatJson_WithGson_defaultConfig_sortByKeys() throws Exception writePomWithJsonSteps(""); setFile("json_test.json").toResource("json/sortByKeysBefore.json"); - mavenRunner().withArguments("spotless:apply").runNoError().error(); + mavenRunner().withArguments("spotless:apply").runNoError(); assertFile("json_test.json").sameAsResource("json/sortByKeysAfterDisabled.json"); } @@ -52,8 +56,20 @@ public void testFormatJson_WithGson_sortByKeys() throws Exception { writePomWithJsonSteps("true"); setFile("json_test.json").toResource("json/sortByKeysBefore.json"); - mavenRunner().withArguments("spotless:apply").runNoError().error(); + + String output = mavenRunner().withArguments("spotless:apply").runNoError().output(); + LOGGER.error(output); + System.err.println(output); assertFile("json_test.json").sameAsResource("json/sortByKeysAfter.json"); } + @Test + public void testFormatJson_WithGson_defaultConfig_nestedObject() throws Exception { + writePomWithJsonSteps(""); + + setFile("json_test.json").toResource("json/nestedObjectBefore.json"); + mavenRunner().withArguments("spotless:apply").runNoError(); + assertFile("json_test.json").sameAsResource("json/nestedObjectAfter.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 4614b42f22..b5a417c536 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,17 +15,27 @@ */ 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); + @Test public void testFormatYaml_WithJackson_defaultConfig_separatorComments() throws Exception { writePomWithYamlSteps(""); setFile("yaml_test.yaml").toResource("yaml/separator_comments.yaml"); - mavenRunner().withArguments("spotless:apply").runNoError().error(); + 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"); assertFile("yaml_test.yaml").sameAsResource("yaml/separator_comments.clean.yaml"); } @@ -34,7 +44,7 @@ public void testFormatYaml_WithJackson_defaultConfig_arrayBrackets() throws Exce writePomWithYamlSteps(""); setFile("yaml_test.yaml").toResource("yaml/array_with_bracket.yaml"); - mavenRunner().withArguments("spotless:apply").runNoError().error(); + mavenRunner().withArguments("spotless:apply").runNoError(); assertFile("yaml_test.yaml").sameAsResource("yaml/array_with_bracket.clean.yaml"); } @@ -43,7 +53,7 @@ public void testFormatYaml_WithJackson_defaultConfig_multipleDocuments() throws writePomWithYamlSteps(""); setFile("yaml_test.yaml").toResource("yaml/multiple_documents.yaml"); - mavenRunner().withArguments("spotless:apply").runNoError().error(); - assertFile("yaml_test.yaml").sameAsResource("yaml/multiple_documents.clean.yaml"); + mavenRunner().withArguments("spotless:apply").runNoError(); + assertFile("yaml_test.yaml").sameAsResource("yaml/multiple_documents.clean.jackson.yaml"); } } diff --git a/testlib/src/main/resources/json/sortByKeysAfterDisabled_Simple.json b/testlib/src/main/resources/json/sortByKeysAfterDisabled_Simple.json new file mode 100644 index 0000000000..d2d3612fbd --- /dev/null +++ b/testlib/src/main/resources/json/sortByKeysAfterDisabled_Simple.json @@ -0,0 +1,19 @@ +{ + "A": 1, + "a": 3, + "c": 4, + "x": 5, + "X": 2, + "z": { + "A": 1, + "a": 3, + "c": 4, + "x": 5, + "X": 2 + }, + "_arraysNotSorted": [ + 3, + 2, + 1 + ] +} diff --git a/testlib/src/main/resources/yaml/multiple_documents.clean.jackson.yaml b/testlib/src/main/resources/yaml/multiple_documents.clean.jackson.yaml new file mode 100644 index 0000000000..aa731919b4 --- /dev/null +++ b/testlib/src/main/resources/yaml/multiple_documents.clean.jackson.yaml @@ -0,0 +1,2 @@ +--- +document: "this is document 1" From fa203e4ebb2606383f8c5253e5fa52a6b9ab9099 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Thu, 12 Jan 2023 11:15:40 +0400 Subject: [PATCH 11/11] Remove reflection impl to rely on glue impl --- lib/build.gradle | 2 +- .../glue/yaml/YamlJacksonFormatterFunc.java | 2 - .../spotless/yaml/YamlJacksonStep.java | 96 +++---------------- .../spotless/yaml/YamlJacksonV2Step.java | 77 --------------- plugin-maven/README.md | 2 +- .../diffplug/spotless/maven/yaml/Jackson.java | 3 +- 6 files changed, 15 insertions(+), 167 deletions(-) delete mode 100644 lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonV2Step.java diff --git a/lib/build.gradle b/lib/build.gradle index 0cf07f9531..3ef2064765 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -57,7 +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.dataformat:jackson-dataformat-yaml:2.13.4' + jacksonCompileOnly 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.14.1' String VER_KTFMT = '0.42' ktfmtCompileOnly "com.facebook:ktfmt:$VER_KTFMT" 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 604ad048c8..30cf538159 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 @@ -31,8 +31,6 @@ public class YamlJacksonFormatterFunc implements FormatterFunc { private List enabledFeatures; private List disabledFeatures; - // private static final Logger logger = LoggerFactory.getLogger(YamlJacksonFormatterFunc.class); - public YamlJacksonFormatterFunc(List enabledFeatures, List disabledFeatures) { this.enabledFeatures = enabledFeatures; this.disabledFeatures = disabledFeatures; diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java index c0c660694b..db2525ab97 100644 --- a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java +++ b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonStep.java @@ -17,8 +17,8 @@ import java.io.IOException; import java.io.Serializable; +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -32,9 +32,12 @@ * 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 final class YamlJacksonStep { +public class YamlJacksonStep { static final String MAVEN_COORDINATE = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:"; - static final String DEFAULT_VERSION = "2.13.4"; + // https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml + static final String DEFAULT_VERSION = "2.14.1"; + + private YamlJacksonStep() {} public static String defaultVersion() { return DEFAULT_VERSION; @@ -69,89 +72,14 @@ private State(List enabledFeatures, this.enabledFeatures = enabledFeatures; this.disabledFeatures = disabledFeatures; - this.jarState = JarState.from(MAVEN_COORDINATE + jacksonVersion, provisioner); + this.jarState = JarState.from(YamlJacksonStep.MAVEN_COORDINATE + jacksonVersion, provisioner); } - FormatterFunc toFormatter() { - Class jsonFactoryClass; - Class yamlFactoryClass; - Class objectMapperClass; - - Class serializationFeatureClass; - Method enableFeature; - Method disableFeature; - - Method stringToNode; - Method nodeToString; - try { - ClassLoader classLoader = jarState.getClassLoader(); - jsonFactoryClass = classLoader.loadClass("com.fasterxml.jackson.core.JsonFactory"); - yamlFactoryClass = classLoader.loadClass("com.fasterxml.jackson.dataformat.yaml.YAMLFactory"); - - objectMapperClass = classLoader.loadClass("com.fasterxml.jackson.databind.ObjectMapper"); - - // Configure the ObjectMapper - // https://github.com/FasterXML/jackson-databind#commonly-used-features - { - serializationFeatureClass = classLoader.loadClass("com.fasterxml.jackson.databind.SerializationFeature"); - enableFeature = objectMapperClass.getMethod("enable", serializationFeatureClass); - disableFeature = objectMapperClass.getMethod("disable", serializationFeatureClass); - } - - // https://stackoverflow.com/questions/25222327/deserialize-pojos-from-multiple-yaml-documents-in-a-single-file-in-jackson - // List docs = mapper - // .readValues(yamlParser, new TypeReference {}) - // .readAll(); - - Class jsonNodeClass = classLoader.loadClass("com.fasterxml.jackson.databind.JsonNode"); - - // This will transit with a JsonNode - // A JsonNode may keep the comments from the input node - stringToNode = objectMapperClass.getMethod("readTree", String.class); - // Not 'toPrettyString' as one could require no INDENT_OUTPUT - nodeToString = jsonNodeClass.getMethod("toPrettyString"); - } catch (ClassNotFoundException | NoSuchMethodException e) { - throw new IllegalStateException("There was a problem preparing org.json dependencies", e); - } - - return s -> { - if (s.isEmpty()) { - return s; - } - - Object yamlFactory = yamlFactoryClass.getConstructor().newInstance(); - Object objectMapper = objectMapperClass.getConstructor(jsonFactoryClass).newInstance(yamlFactory); - - for (String feature : enabledFeatures) { - // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection - Object indentOutput = Enum.valueOf(serializationFeatureClass.asSubclass(Enum.class), feature); - - enableFeature.invoke(objectMapper, indentOutput); - } - - for (String feature : disabledFeatures) { - // https://stackoverflow.com/questions/3735927/java-instantiating-an-enum-using-reflection - Object indentOutput = Enum.valueOf(serializationFeatureClass.asSubclass(Enum.class), feature); - - disableFeature.invoke(objectMapper, indentOutput); - } - - return format(objectMapper, stringToNode, nodeToString, s); - }; + 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); } - - private String format(Object objectMapper, Method stringToNode, Method nodeToString, String s) - throws IllegalAccessException, IllegalArgumentException { - try { - Object node = stringToNode.invoke(objectMapper, s); - return (String) nodeToString.invoke(node); - } catch (InvocationTargetException ex) { - throw new AssertionError("Unable to format YAML", ex.getCause()); - } - } - } - - private YamlJacksonStep() { - // cannot be directly instantiated } } diff --git a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonV2Step.java b/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonV2Step.java deleted file mode 100644 index f9b1d6b7dc..0000000000 --- a/lib/src/main/java/com/diffplug/spotless/yaml/YamlJacksonV2Step.java +++ /dev/null @@ -1,77 +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.yaml; - -import java.io.IOException; -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; - -public class YamlJacksonV2Step { - private YamlJacksonV2Step() {} - - public static String defaultVersion() { - return YamlJacksonStep.DEFAULT_VERSION; - } - - public static FormatterStep create(List enabledFeatures, - List disabledFeatures, - String jacksonVersion, - Provisioner provisioner) { - Objects.requireNonNull(provisioner, "provisioner cannot be null"); - return FormatterStep.createLazy("yaml", - () -> new State(enabledFeatures, disabledFeatures, jacksonVersion, provisioner), - State::toFormatter); - } - - public static FormatterStep create(Provisioner provisioner) { - return create(Arrays.asList("INDENT_OUTPUT"), Arrays.asList(), 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 JarState jarState; - - private State(List enabledFeatures, - List disabledFeatures, - String jacksonVersion, - Provisioner provisioner) throws IOException { - this.enabledFeatures = enabledFeatures; - this.disabledFeatures = disabledFeatures; - - this.jarState = JarState.from(YamlJacksonStep.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); - } - } -} diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 720c9bfee7..c5c5cf0ac3 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -923,7 +923,7 @@ Uses Jackson and YAMLFactory to pretty print objects: ```xml - 2.13.4 + 2.14.1 INDENT_OUTPUT 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/yaml/Jackson.java index 28fdf5809c..2bc7617a38 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Jackson.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/yaml/Jackson.java @@ -24,7 +24,6 @@ import com.diffplug.spotless.maven.FormatterStepConfig; import com.diffplug.spotless.maven.FormatterStepFactory; import com.diffplug.spotless.yaml.YamlJacksonStep; -import com.diffplug.spotless.yaml.YamlJacksonV2Step; public class Jackson implements FormatterStepFactory { @@ -41,7 +40,7 @@ public class Jackson implements FormatterStepFactory { public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) { List enabledFeaturesAsList = Arrays.asList(enabledFeatures); List disabledFeaturesAsList = Arrays.asList(disabledFeatures); - return YamlJacksonV2Step + return YamlJacksonStep .create(enabledFeaturesAsList, disabledFeaturesAsList, version, stepConfig.getProvisioner()); } }