From 6419de194845da533ecfb1a0bb1afd92e07dab0e Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Thu, 11 Jan 2024 18:04:39 +0300 Subject: [PATCH 01/12] Basic IDEA usage locally. Thought of implementation plan, experimented with code dependencies using tests. --- .../com/diffplug/spotless/java/IdeaStep.java | 40 +++++++++++++++ .../main/resources/java/idea/full.clean.java | 14 ++++++ .../main/resources/java/idea/full.dirty.java | 22 ++++++++ .../diffplug/spotless/java/IdeaStepTest.java | 50 +++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java create mode 100644 testlib/src/main/resources/java/idea/full.clean.java create mode 100644 testlib/src/main/resources/java/idea/full.dirty.java create mode 100644 testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java new file mode 100644 index 0000000000..3c3021b644 --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java @@ -0,0 +1,40 @@ +package com.diffplug.spotless.java; + +import java.io.File; +import java.nio.file.Files; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.ProcessRunner; + +public class IdeaStep { + + private static final Logger LOGGER = + LoggerFactory.getLogger(IdeaStep.class); + + public static FormatterStep create() { + // TODO: make it lazy + return FormatterStep.createNeverUpToDate("IDEA", + new FormatterFunc.NeedsFile() { + + // TODO: parameterize so user is able to provide it's own file + // TODO: Use ForeignExe to ensure file + private final String binaryPath = + "idea"; + + @Override + public String applyWithFile(String unix, File file) + throws Exception { + try (ProcessRunner runner = new ProcessRunner()) { + var result = runner.exec(binaryPath, "format", + "-allowDefaults", file.toString()); + LOGGER.debug("command finished with stdout: {}", + result.stdOutUtf8()); + return Files.readString(file.toPath()); + } + } + }); + } + +} diff --git a/testlib/src/main/resources/java/idea/full.clean.java b/testlib/src/main/resources/java/idea/full.clean.java new file mode 100644 index 0000000000..84d76d4650 --- /dev/null +++ b/testlib/src/main/resources/java/idea/full.clean.java @@ -0,0 +1,14 @@ +package com.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} + diff --git a/testlib/src/main/resources/java/idea/full.dirty.java b/testlib/src/main/resources/java/idea/full.dirty.java new file mode 100644 index 0000000000..83923130e6 --- /dev/null +++ b/testlib/src/main/resources/java/idea/full.dirty.java @@ -0,0 +1,22 @@ +package com.example; + +import org.springframework.boot.SpringApplication; + + + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@ + +SpringBootApplication +public + + +class Application{ + + public static void main( String[] args) { + SpringApplication. run(Application.class, args); + } + +} + diff --git a/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java new file mode 100644 index 0000000000..6a7e066b48 --- /dev/null +++ b/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java @@ -0,0 +1,50 @@ +package com.diffplug.spotless.java; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import com.diffplug.common.io.Files; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.ResourceHarness; + +class IdeaStepTest extends ResourceHarness { + + @Test + void name() throws Exception { + FormatterStep step = IdeaStep.create(); + + String name = step.getName(); + + Assertions.assertEquals("IDEA", name); + } + + @Test + void notFormattings() throws Exception { + File cleanFile = newFile("clean.java"); + String cleanJava = + ResourceHarness.getTestResource("java/idea/full.clean.java"); + Files.write(cleanJava, cleanFile, StandardCharsets.UTF_8); + FormatterStep step = IdeaStep.create(); + + var result = step.format(cleanJava, cleanFile); + + Assertions.assertEquals(cleanJava, result, + "formatting was applied to clean file"); + } + + @Test + void formattings() throws Exception { + File dirtyFile = newFile("dirty.java"); + String dirtyJava = + ResourceHarness.getTestResource("java/idea/full.dirty.java"); + Files.write(dirtyJava, dirtyFile, StandardCharsets.UTF_8); + FormatterStep step = IdeaStep.create(); + + var result = step.format(dirtyJava, dirtyFile); + + Assertions.assertNotEquals(dirtyJava, result, + "files were not changed after reformat"); + } + +} From b84d24331f2839ca628867cb66fa94d4dbb48664 Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Tue, 23 Jan 2024 22:31:38 +0300 Subject: [PATCH 02/12] Parameterize IDEA usage. Added parameterized method to call idea formatter. --- .../spotless/java/IdeaFormatterFunc.java | 66 +++++++++++++++++++ .../com/diffplug/spotless/java/IdeaStep.java | 52 +++++++-------- .../diffplug/spotless/java/IdeaStepTest.java | 45 ++++++++++++- 3 files changed, 132 insertions(+), 31 deletions(-) create mode 100644 lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java b/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java new file mode 100644 index 0000000000..55e9989bda --- /dev/null +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java @@ -0,0 +1,66 @@ +package com.diffplug.spotless.java; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.diffplug.spotless.FormatterFunc; +import com.diffplug.spotless.ProcessRunner; + +public final class IdeaFormatterFunc implements FormatterFunc.NeedsFile { + + private static final Logger LOGGER = + LoggerFactory.getLogger(IdeaStep.class); + + private static final String DEFAULT_IDEA = "idea"; + + // TODO: Use ForeignExe to ensure file + private final String binaryPath; + private final boolean withDefaults; + + private IdeaFormatterFunc(boolean withDefaults, String binaryPath) { + this.withDefaults = withDefaults; + this.binaryPath = Objects.requireNonNullElse(binaryPath, DEFAULT_IDEA); + } + + public static IdeaFormatterFunc allowingDefaultsWithCustomBinary( + String binaryPath) { + return new IdeaFormatterFunc(true, binaryPath); + } + + public static IdeaFormatterFunc noDefaultsWithCustomBinary( + String binaryPath) { + return new IdeaFormatterFunc(false, binaryPath); + } + + @Override + public String applyWithFile(String unix, File file) throws Exception { + List params = getParams(file); + + try (ProcessRunner runner = new ProcessRunner()) { + var result = runner.exec(params); + + LOGGER.debug("command finished with stdout: {}", + result.assertExitZero(StandardCharsets.UTF_8)); + + return Files.readString(file.toPath()); + } + } + + private List getParams(File file) { + var builder = Stream.builder(); + builder.add(binaryPath); + builder.add("format"); + if (withDefaults) { + builder.add("-allowDefaults"); + } + builder.add(file.toString()); + return builder.build().collect(Collectors.toList()); + } + +} diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java index 3c3021b644..a2240a067d 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java @@ -1,40 +1,34 @@ package com.diffplug.spotless.java; -import java.io.File; -import java.nio.file.Files; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; -import com.diffplug.spotless.ProcessRunner; -public class IdeaStep { +public final class IdeaStep { - private static final Logger LOGGER = - LoggerFactory.getLogger(IdeaStep.class); + private IdeaStep() {} public static FormatterStep create() { + return create(true); + } + + public static FormatterStep create(boolean withDefaults) { + return create(true, null); + } + + public static FormatterStep create(boolean withDefaults, + String binaryPath) { + IdeaFormatterFunc formatterFunc = + getFormatterFunc(withDefaults, binaryPath); // TODO: make it lazy - return FormatterStep.createNeverUpToDate("IDEA", - new FormatterFunc.NeedsFile() { - - // TODO: parameterize so user is able to provide it's own file - // TODO: Use ForeignExe to ensure file - private final String binaryPath = - "idea"; - - @Override - public String applyWithFile(String unix, File file) - throws Exception { - try (ProcessRunner runner = new ProcessRunner()) { - var result = runner.exec(binaryPath, "format", - "-allowDefaults", file.toString()); - LOGGER.debug("command finished with stdout: {}", - result.stdOutUtf8()); - return Files.readString(file.toPath()); - } - } - }); + return FormatterStep.createNeverUpToDate("IDEA", formatterFunc); + } + + private static IdeaFormatterFunc getFormatterFunc(boolean withDefaults, + String binaryPath) { + if (withDefaults) { + return IdeaFormatterFunc + .allowingDefaultsWithCustomBinary(binaryPath); + } + return IdeaFormatterFunc.noDefaultsWithCustomBinary(binaryPath); } } diff --git a/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java index 6a7e066b48..670faa7c8b 100644 --- a/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java @@ -12,7 +12,7 @@ class IdeaStepTest extends ResourceHarness { @Test void name() throws Exception { - FormatterStep step = IdeaStep.create(); + FormatterStep step = IdeaStep.create(true, "idea"); String name = step.getName(); @@ -25,7 +25,7 @@ void notFormattings() throws Exception { String cleanJava = ResourceHarness.getTestResource("java/idea/full.clean.java"); Files.write(cleanJava, cleanFile, StandardCharsets.UTF_8); - FormatterStep step = IdeaStep.create(); + FormatterStep step = IdeaStep.create(true, "idea"); var result = step.format(cleanJava, cleanFile); @@ -35,6 +35,20 @@ void notFormattings() throws Exception { @Test void formattings() throws Exception { + File dirtyFile = newFile("dirty.java"); + String dirtyJava = + ResourceHarness.getTestResource("java/idea/full.dirty.java"); + Files.write(dirtyJava, dirtyFile, StandardCharsets.UTF_8); + FormatterStep step = IdeaStep.create(true, "idea"); + + var result = step.format(dirtyJava, dirtyFile); + + Assertions.assertNotEquals(dirtyJava, result, + "files were not changed after reformat"); + } + + @Test + void formattingsWorkWithDefaultParameters() throws Exception { File dirtyFile = newFile("dirty.java"); String dirtyJava = ResourceHarness.getTestResource("java/idea/full.dirty.java"); @@ -47,4 +61,31 @@ void formattings() throws Exception { "files were not changed after reformat"); } + @Test + void formattingsNotDeafaultDoesNothing() throws Exception { + File dirtyFile = newFile("dirty.java"); + String dirtyJava = + ResourceHarness.getTestResource("java/idea/full.dirty.java"); + Files.write(dirtyJava, dirtyFile, StandardCharsets.UTF_8); + FormatterStep step = IdeaStep.create(false, "idea"); + + var result = step.format(dirtyJava, dirtyFile); + + Assertions.assertEquals(dirtyJava, result, + "files were changed after reformat"); + } + + @Test + void configureFile() throws Exception { + File cleanFile = newFile("clean.java"); + String cleanJava = + ResourceHarness.getTestResource("java/idea/full.clean.java"); + Files.write(cleanJava, cleanFile, StandardCharsets.UTF_8); + FormatterStep step = IdeaStep.create(true, "idea"); + + var result = step.format(cleanJava, cleanFile); + + Assertions.assertEquals(cleanJava, result, + "formatting was applied to clean file"); + } } From 1d8d9b20034fa00558036d718ae2429519e1229c Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Tue, 23 Jan 2024 22:46:43 +0300 Subject: [PATCH 03/12] Verify IDEA binary. Used ForeignExe to check idea binary --- .../spotless/java/IdeaFormatterFunc.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java b/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java index 55e9989bda..68d26bc304 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java @@ -1,14 +1,17 @@ package com.diffplug.spotless.java; import java.io.File; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.List; import java.util.Objects; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.diffplug.spotless.ForeignExe; import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.ProcessRunner; @@ -19,13 +22,30 @@ public final class IdeaFormatterFunc implements FormatterFunc.NeedsFile { private static final String DEFAULT_IDEA = "idea"; - // TODO: Use ForeignExe to ensure file - private final String binaryPath; - private final boolean withDefaults; + private String binaryPath; + private boolean withDefaults; private IdeaFormatterFunc(boolean withDefaults, String binaryPath) { this.withDefaults = withDefaults; this.binaryPath = Objects.requireNonNullElse(binaryPath, DEFAULT_IDEA); + resolveFullBinaryPathAndCheckVersion(); + } + + private void resolveFullBinaryPathAndCheckVersion() { + var exe = ForeignExe.nameAndVersion(this.binaryPath, "IntelliJ IDEA") + .versionRegex(Pattern.compile("(IntelliJ IDEA) .*")) + .fixCantFind("IDEA executable cannot be found on your machine, " + + "please install it and put idea binary to PATH; or report the problem") + .fixWrongVersion("Provided binary is not IDEA, " + + "please check it and fix the problem; or report the problem"); + try { + this.binaryPath = exe.confirmVersionAndGetAbsolutePath(); + } catch (IOException e) { + throw new IllegalArgumentException("binary cannot be found", e); + } catch (InterruptedException e) { + throw new IllegalArgumentException( + "binary cannot be found, process was interrupted", e); + } } public static IdeaFormatterFunc allowingDefaultsWithCustomBinary( From affd905be602b818e3084ffe186ae1149b829eb1 Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Tue, 23 Jan 2024 23:17:24 +0300 Subject: [PATCH 04/12] Gradle IDEA integration. IDEA running using gradle --- .../gradle/spotless/JavaExtension.java | 34 ++++++++++++++- .../gradle/spotless/JavaIdeaTest.java | 41 +++++++++++++++++++ .../diffplug/spotless/ResourceHarness.java | 12 ++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java index db869dc4e6..a191e3ef50 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java @@ -39,6 +39,7 @@ import com.diffplug.spotless.java.CleanthatJavaStep; import com.diffplug.spotless.java.FormatAnnotationsStep; import com.diffplug.spotless.java.GoogleJavaFormatStep; +import com.diffplug.spotless.java.IdeaStep; import com.diffplug.spotless.java.ImportOrderStep; import com.diffplug.spotless.java.PalantirJavaFormatStep; import com.diffplug.spotless.java.RemoveUnusedImportsStep; @@ -313,6 +314,37 @@ public EclipseConfig withP2Mirrors(Map mirrors) { } + public IdeaConfig idea() { + return new IdeaConfig(); + } + + public class IdeaConfig { + String binaryPath; + boolean withDefaults = false; + + IdeaConfig() { + addStep(createStep()); + } + + private FormatterStep createStep() { + return IdeaStep.create(withDefaults, binaryPath); + } + + public IdeaConfig binaryPath(String binaryPath) { + Objects.requireNonNull(binaryPath); + this.binaryPath = binaryPath; + replaceStep(createStep()); + return this; + } + + public IdeaConfig withDefaults(Boolean withDefaults) { + Objects.requireNonNull(withDefaults); + this.withDefaults = withDefaults; + replaceStep(createStep()); + return this; + } + } + /** Removes newlines between type annotations and types. */ public FormatAnnotationsConfig formatAnnotations() { return new FormatAnnotationsConfig(); @@ -400,7 +432,7 @@ public CleanthatJavaConfig clearMutators() { } // An id of a mutator (see IMutator.getIds()) or - // tThe fully qualified name of a class implementing eu.solven.cleanthat.engine.java.refactorer.meta.IMutator + // The fully qualified name of a class implementing eu.solven.cleanthat.engine.java.refactorer.meta.IMutator public CleanthatJavaConfig addMutator(String mutator) { this.mutators.add(mutator); replaceStep(createStep()); diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java new file mode 100644 index 0000000000..d899b13203 --- /dev/null +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020-2024 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 JavaIdeaTest extends GradleIntegrationHarness { + @Test + void idea() throws IOException { + setFile("build.gradle").toLines( + "plugins {", + " id 'com.diffplug.spotless'", + "}", + "spotless {", + " java {", + " target file('test.java')", + " idea().binaryPath('idea').withDefaults(true)", + " }", + "}"); + + setFile("test.java").toResource("java/idea/full.dirty.java"); + gradleRunner().withArguments("spotlessApply").build(); + assertFile("test.java").notSameAsResource("java/idea/full.dirty.java"); + } +} diff --git a/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java index 0304889e1f..fcdfa2f97d 100644 --- a/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java +++ b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java @@ -151,10 +151,18 @@ public void hasContent(String expected) { hasContent(expected, StandardCharsets.UTF_8); } + public void hasDifferentContent(String expected) { + hasDifferentContent(expected, StandardCharsets.UTF_8); + } + public void hasContent(String expected, Charset charset) { assertThat(file).usingCharset(charset).hasContent(expected); } + public void hasDifferentContent(String expected, Charset charset) { + assertThat(file).usingCharset(charset).isNotEqualTo(expected); + } + public void hasLines(String... lines) { hasContent(String.join("\n", Arrays.asList(lines))); } @@ -163,6 +171,10 @@ public void sameAsResource(String resource) throws IOException { hasContent(getTestResource(resource)); } + public void notSameAsResource(String resource) throws IOException { + hasDifferentContent(getTestResource(resource)); + } + public void matches(Consumer> conditions) throws IOException { String content = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); conditions.accept(assertThat(content)); From effe2fcfdb0679598b6c83d2cd9dbbc965237c03 Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Tue, 23 Jan 2024 23:26:10 +0300 Subject: [PATCH 05/12] Maven IDEA integration. IDEA running using maven --- .../diffplug/spotless/maven/java/Idea.java | 36 +++++++++++++++++++ .../diffplug/spotless/maven/java/Java.java | 4 +++ .../spotless/maven/java/IdeaTest.java | 36 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java create mode 100644 plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java new file mode 100644 index 0000000000..182178c797 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016-2024 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.java; + +import org.apache.maven.plugins.annotations.Parameter; +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.java.IdeaStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class Idea implements FormatterStepFactory { + + @Parameter + private String binaryPath; + + @Parameter + private Boolean withDefaults = false; + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig config) { + return IdeaStep.create(withDefaults, binaryPath); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java index b0692446b7..751da56ae9 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java @@ -68,6 +68,10 @@ public void addImportOrder(ImportOrder importOrder) { addStepFactory(importOrder); } + public void addIdea(Idea idea) { + addStepFactory(idea); + } + public void addPalantirJavaFormat(PalantirJavaFormat palantirJavaFormat) { addStepFactory(palantirJavaFormat); } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java new file mode 100644 index 0000000000..05747eae06 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016-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.maven.java; + +import org.junit.jupiter.api.Test; + +import com.diffplug.spotless.maven.MavenIntegrationHarness; + +class IdeaTest extends MavenIntegrationHarness { + @Test + void idea() throws Exception { + setFile("test.java").toResource("java/cleanthat/MultipleMutators.dirty.test"); + writePomWithJavaSteps( + "", + " idea", + " true", + ""); + + mavenRunner().withArguments("spotless:apply").runNoError(); + + assertFile("test.java").notSameAsResource("java/cleanthat/MultipleMutators.dirty.test"); + } +} From 8e301758f6e70d55b2d8dd3db3aff8214bf4b117 Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Tue, 23 Jan 2024 23:30:56 +0300 Subject: [PATCH 06/12] Make IDEA tests special As described here: https://github.com/diffplug/spotless/issues/200#issuecomment-1905302847 --- gradle/special-tests.gradle | 1 + .../gradle/spotless/JavaIdeaTest.java | 3 +- .../spotless/maven/java/IdeaTest.java | 1 + .../com/diffplug/spotless/tag/IdeaTest.java | 30 +++++++++++++++++++ .../diffplug/spotless/java/IdeaStepTest.java | 2 ++ 5 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 testlib/src/main/java/com/diffplug/spotless/tag/IdeaTest.java diff --git a/gradle/special-tests.gradle b/gradle/special-tests.gradle index 8d9004a709..58a21f0cb2 100644 --- a/gradle/special-tests.gradle +++ b/gradle/special-tests.gradle @@ -6,6 +6,7 @@ def special = [ 'Buf', 'Clang', 'gofmt', + 'idea', 'Npm', 'Shfmt' ] diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java index d899b13203..2e51f26bb0 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java @@ -18,8 +18,9 @@ import java.io.IOException; import org.junit.jupiter.api.Test; +import com.diffplug.spotless.tag.IdeaTest; - +@IdeaTest class JavaIdeaTest extends GradleIntegrationHarness { @Test void idea() throws IOException { diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java index 05747eae06..575f88c29c 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java @@ -19,6 +19,7 @@ import com.diffplug.spotless.maven.MavenIntegrationHarness; +@com.diffplug.spotless.tag.IdeaTest class IdeaTest extends MavenIntegrationHarness { @Test void idea() throws Exception { diff --git a/testlib/src/main/java/com/diffplug/spotless/tag/IdeaTest.java b/testlib/src/main/java/com/diffplug/spotless/tag/IdeaTest.java new file mode 100644 index 0000000000..79813d91d9 --- /dev/null +++ b/testlib/src/main/java/com/diffplug/spotless/tag/IdeaTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2021-2024 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.tag; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.Tag; + +@Target({TYPE, METHOD}) +@Retention(RUNTIME) +@Tag("idea") +public @interface IdeaTest {} diff --git a/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java index 670faa7c8b..b750fb5677 100644 --- a/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java @@ -7,7 +7,9 @@ import com.diffplug.common.io.Files; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.ResourceHarness; +import com.diffplug.spotless.tag.IdeaTest; +@IdeaTest class IdeaStepTest extends ResourceHarness { @Test From 1554dd6c25d293ed62d872f250aae300e32f81e9 Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Tue, 23 Jan 2024 23:41:17 +0300 Subject: [PATCH 07/12] docs: CHANGES.md --- CHANGES.md | 2 ++ plugin-gradle/CHANGES.md | 2 ++ plugin-maven/CHANGES.md | 2 ++ 3 files changed, 6 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index adf6d109e7..0e6eb2a8c7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] +* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020)) + ## [2.45.0] - 2024-01-23 ### Added * Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/pull/2001)) diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index d4ce3b410e..1f81da2ccb 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] +* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020)) + ## [6.25.0] - 2024-01-23 ### Added * Maven / Gradle - Support for formatting Java Docs for the Palantir formatter ([#2009](https://github.com/diffplug/spotless/pull/2009)) diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 56cd5a5104..7488008b05 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -4,6 +4,8 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] +* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020)) + ## [2.43.0] - 2024-01-23 ### Added * Support for formatting shell scripts via [shfmt](https://github.com/mvdan/sh). ([#1998](https://github.com/diffplug/spotless/issues/1998)) From 763eaac98a888f463759cd86a2bc271b688acfb3 Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Tue, 23 Jan 2024 23:57:02 +0300 Subject: [PATCH 08/12] Config file for IDEA step This part is lacking tests due to unpredictable nature of IDEA formatting. They may change configs thus breaking build. --- .../spotless/java/IdeaFormatterFunc.java | 17 ++++++++++++----- .../com/diffplug/spotless/java/IdeaStep.java | 13 +++++++++---- .../diffplug/gradle/spotless/JavaExtension.java | 8 ++++++++ .../com/diffplug/spotless/maven/java/Idea.java | 5 ++++- .../diffplug/spotless/java/IdeaStepTest.java | 2 +- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java b/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java index 68d26bc304..282ff37f07 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java @@ -23,10 +23,13 @@ public final class IdeaFormatterFunc implements FormatterFunc.NeedsFile { private static final String DEFAULT_IDEA = "idea"; private String binaryPath; + private String configPath; private boolean withDefaults; - private IdeaFormatterFunc(boolean withDefaults, String binaryPath) { + private IdeaFormatterFunc(boolean withDefaults, String binaryPath, + String configPath) { this.withDefaults = withDefaults; + this.configPath = configPath; this.binaryPath = Objects.requireNonNullElse(binaryPath, DEFAULT_IDEA); resolveFullBinaryPathAndCheckVersion(); } @@ -49,13 +52,13 @@ private void resolveFullBinaryPathAndCheckVersion() { } public static IdeaFormatterFunc allowingDefaultsWithCustomBinary( - String binaryPath) { - return new IdeaFormatterFunc(true, binaryPath); + String binaryPath, String configPath) { + return new IdeaFormatterFunc(true, binaryPath, configPath); } public static IdeaFormatterFunc noDefaultsWithCustomBinary( - String binaryPath) { - return new IdeaFormatterFunc(false, binaryPath); + String binaryPath, String configPath) { + return new IdeaFormatterFunc(false, binaryPath, configPath); } @Override @@ -79,6 +82,10 @@ private List getParams(File file) { if (withDefaults) { builder.add("-allowDefaults"); } + if (configPath != null) { + builder.add("-s"); + builder.add(configPath); + } builder.add(file.toString()); return builder.build().collect(Collectors.toList()); } diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java index a2240a067d..b4efee7c04 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java @@ -16,19 +16,24 @@ public static FormatterStep create(boolean withDefaults) { public static FormatterStep create(boolean withDefaults, String binaryPath) { + return create(withDefaults, binaryPath, null); + } + + public static FormatterStep create(boolean withDefaults, + String binaryPath, String configPath) { IdeaFormatterFunc formatterFunc = - getFormatterFunc(withDefaults, binaryPath); + getFormatterFunc(withDefaults, binaryPath, configPath); // TODO: make it lazy return FormatterStep.createNeverUpToDate("IDEA", formatterFunc); } private static IdeaFormatterFunc getFormatterFunc(boolean withDefaults, - String binaryPath) { + String binaryPath, String configPath) { if (withDefaults) { return IdeaFormatterFunc - .allowingDefaultsWithCustomBinary(binaryPath); + .allowingDefaultsWithCustomBinary(binaryPath, configPath); } - return IdeaFormatterFunc.noDefaultsWithCustomBinary(binaryPath); + return IdeaFormatterFunc.noDefaultsWithCustomBinary(binaryPath, configPath); } } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java index a191e3ef50..98617fa787 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java @@ -320,6 +320,7 @@ public IdeaConfig idea() { public class IdeaConfig { String binaryPath; + String configPath; boolean withDefaults = false; IdeaConfig() { @@ -337,6 +338,13 @@ public IdeaConfig binaryPath(String binaryPath) { return this; } + public IdeaConfig configPath(String configPath) { + Objects.requireNonNull(configPath); + this.configPath = configPath; + replaceStep(createStep()); + return this; + } + public IdeaConfig withDefaults(Boolean withDefaults) { Objects.requireNonNull(withDefaults); this.withDefaults = withDefaults; diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java index 182178c797..83decc6867 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java @@ -26,11 +26,14 @@ public class Idea implements FormatterStepFactory { @Parameter private String binaryPath; + @Parameter + private String configPath; + @Parameter private Boolean withDefaults = false; @Override public FormatterStep newFormatterStep(FormatterStepConfig config) { - return IdeaStep.create(withDefaults, binaryPath); + return IdeaStep.create(withDefaults, binaryPath, configPath); } } diff --git a/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java index b750fb5677..38606c3657 100644 --- a/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java @@ -64,7 +64,7 @@ void formattingsWorkWithDefaultParameters() throws Exception { } @Test - void formattingsNotDeafaultDoesNothing() throws Exception { + void formattingsWithOutDefaultDoesNothing() throws Exception { File dirtyFile = newFile("dirty.java"); String dirtyJava = ResourceHarness.getTestResource("java/idea/full.dirty.java"); From fdb73b7994f8c15c69e9d3017d8a27eac471d664 Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Wed, 24 Jan 2024 09:56:28 +0300 Subject: [PATCH 09/12] CI Fixes --- .../spotless/java/IdeaFormatterFunc.java | 33 +++++++++++++++---- .../com/diffplug/spotless/java/IdeaStep.java | 28 ++++++++++++---- .../gradle/spotless/JavaExtension.java | 8 ++--- 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java b/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java index 282ff37f07..779dc3b563 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java @@ -1,3 +1,18 @@ +/* + * Copyright 2024 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.java; import java.io.File; @@ -9,25 +24,29 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; + +import javax.annotation.Nullable; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import com.diffplug.spotless.ForeignExe; import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.ProcessRunner; public final class IdeaFormatterFunc implements FormatterFunc.NeedsFile { - private static final Logger LOGGER = - LoggerFactory.getLogger(IdeaStep.class); + private static final Logger LOGGER = LoggerFactory.getLogger(IdeaStep.class); private static final String DEFAULT_IDEA = "idea"; private String binaryPath; + @Nullable private String configPath; private boolean withDefaults; - private IdeaFormatterFunc(boolean withDefaults, String binaryPath, - String configPath) { + private IdeaFormatterFunc(boolean withDefaults, @Nullable String binaryPath, + @Nullable String configPath) { this.withDefaults = withDefaults; this.configPath = configPath; this.binaryPath = Objects.requireNonNullElse(binaryPath, DEFAULT_IDEA); @@ -52,12 +71,12 @@ private void resolveFullBinaryPathAndCheckVersion() { } public static IdeaFormatterFunc allowingDefaultsWithCustomBinary( - String binaryPath, String configPath) { + @Nullable String binaryPath, @Nullable String configPath) { return new IdeaFormatterFunc(true, binaryPath, configPath); } public static IdeaFormatterFunc noDefaultsWithCustomBinary( - String binaryPath, String configPath) { + @Nullable String binaryPath, @Nullable String configPath) { return new IdeaFormatterFunc(false, binaryPath, configPath); } @@ -76,7 +95,7 @@ public String applyWithFile(String unix, File file) throws Exception { } private List getParams(File file) { - var builder = Stream.builder(); + var builder = Stream. builder(); builder.add(binaryPath); builder.add("format"); if (withDefaults) { diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java index b4efee7c04..8839bbdba0 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java @@ -1,5 +1,22 @@ +/* + * Copyright 2024 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.java; +import javax.annotation.Nullable; + import com.diffplug.spotless.FormatterStep; public final class IdeaStep { @@ -11,24 +28,23 @@ public static FormatterStep create() { } public static FormatterStep create(boolean withDefaults) { - return create(true, null); + return create(withDefaults, null); } public static FormatterStep create(boolean withDefaults, - String binaryPath) { + @Nullable String binaryPath) { return create(withDefaults, binaryPath, null); } public static FormatterStep create(boolean withDefaults, - String binaryPath, String configPath) { - IdeaFormatterFunc formatterFunc = - getFormatterFunc(withDefaults, binaryPath, configPath); + @Nullable String binaryPath, @Nullable String configPath) { + IdeaFormatterFunc formatterFunc = getFormatterFunc(withDefaults, binaryPath, configPath); // TODO: make it lazy return FormatterStep.createNeverUpToDate("IDEA", formatterFunc); } private static IdeaFormatterFunc getFormatterFunc(boolean withDefaults, - String binaryPath, String configPath) { + @Nullable String binaryPath, @Nullable String configPath) { if (withDefaults) { return IdeaFormatterFunc .allowingDefaultsWithCustomBinary(binaryPath, configPath); diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java index 98617fa787..5acd080d16 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java @@ -319,16 +319,16 @@ public IdeaConfig idea() { } public class IdeaConfig { - String binaryPath; - String configPath; - boolean withDefaults = false; + private String binaryPath; + private String configPath; + private boolean withDefaults = false; IdeaConfig() { addStep(createStep()); } private FormatterStep createStep() { - return IdeaStep.create(withDefaults, binaryPath); + return IdeaStep.create(withDefaults, binaryPath, configPath); } public IdeaConfig binaryPath(String binaryPath) { From c6c6ccefc0fa4c7dbc18c51badc8571d9484eaf0 Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Wed, 24 Jan 2024 10:11:17 +0300 Subject: [PATCH 10/12] docs: fixed structure of CHANGES.md --- CHANGES.md | 3 +-- plugin-gradle/CHANGES.md | 4 ++-- plugin-maven/CHANGES.md | 3 ++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2dc29c4809..d3bace3e90 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,13 +12,12 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ## [Unreleased] ### Added * `FileSignature.Promised` and `JarState.Promised` to facilitate round-trip serialization for the Gradle configuration cache. ([#1945](https://github.com/diffplug/spotless/pull/1945)) +* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020)) ### Removed * **BREAKING** Remove `JarState.getMavenCoordinate(String prefix)`. ([#1945](https://github.com/diffplug/spotless/pull/1945)) ### Fixed * Ignore system git config when running tests ([#1990](https://github.com/diffplug/spotless/issues/1990)) -* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020)) - ## [2.45.0] - 2024-01-23 ### Added * Support for `gofmt` ([#2001](https://github.com/diffplug/spotless/pull/2001)) diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 1544f9b705..bb03847254 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -3,11 +3,11 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`). ## [Unreleased] +### Added +* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020)) ### Fixed * Ignore system git config when running tests ([#1990](https://github.com/diffplug/spotless/issues/1990)) -* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020)) - ## [6.25.0] - 2024-01-23 ### Added * Maven / Gradle - Support for formatting Java Docs for the Palantir formatter ([#2009](https://github.com/diffplug/spotless/pull/2009)) diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 57607c5637..17f50162b4 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -3,10 +3,11 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`). ## [Unreleased] +### Added +* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020)) ### Fixed * Ignore system git config when running tests ([#1990](https://github.com/diffplug/spotless/issues/1990)) -* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020)) ## [2.43.0] - 2024-01-23 ### Added From 91235270c3abfaef00927e2606c850d9c7eb9d54 Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Sat, 27 Jan 2024 14:44:13 +0300 Subject: [PATCH 11/12] Create State object This object is now resides in IdeaStep --- .../spotless/java/IdeaFormatterFunc.java | 112 ------------------ .../com/diffplug/spotless/java/IdeaStep.java | 100 ++++++++++++++-- 2 files changed, 91 insertions(+), 121 deletions(-) delete mode 100644 lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java b/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java deleted file mode 100644 index 779dc3b563..0000000000 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaFormatterFunc.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2024 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.java; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.List; -import java.util.Objects; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import javax.annotation.Nullable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.diffplug.spotless.ForeignExe; -import com.diffplug.spotless.FormatterFunc; -import com.diffplug.spotless.ProcessRunner; - -public final class IdeaFormatterFunc implements FormatterFunc.NeedsFile { - - private static final Logger LOGGER = LoggerFactory.getLogger(IdeaStep.class); - - private static final String DEFAULT_IDEA = "idea"; - - private String binaryPath; - @Nullable - private String configPath; - private boolean withDefaults; - - private IdeaFormatterFunc(boolean withDefaults, @Nullable String binaryPath, - @Nullable String configPath) { - this.withDefaults = withDefaults; - this.configPath = configPath; - this.binaryPath = Objects.requireNonNullElse(binaryPath, DEFAULT_IDEA); - resolveFullBinaryPathAndCheckVersion(); - } - - private void resolveFullBinaryPathAndCheckVersion() { - var exe = ForeignExe.nameAndVersion(this.binaryPath, "IntelliJ IDEA") - .versionRegex(Pattern.compile("(IntelliJ IDEA) .*")) - .fixCantFind("IDEA executable cannot be found on your machine, " - + "please install it and put idea binary to PATH; or report the problem") - .fixWrongVersion("Provided binary is not IDEA, " - + "please check it and fix the problem; or report the problem"); - try { - this.binaryPath = exe.confirmVersionAndGetAbsolutePath(); - } catch (IOException e) { - throw new IllegalArgumentException("binary cannot be found", e); - } catch (InterruptedException e) { - throw new IllegalArgumentException( - "binary cannot be found, process was interrupted", e); - } - } - - public static IdeaFormatterFunc allowingDefaultsWithCustomBinary( - @Nullable String binaryPath, @Nullable String configPath) { - return new IdeaFormatterFunc(true, binaryPath, configPath); - } - - public static IdeaFormatterFunc noDefaultsWithCustomBinary( - @Nullable String binaryPath, @Nullable String configPath) { - return new IdeaFormatterFunc(false, binaryPath, configPath); - } - - @Override - public String applyWithFile(String unix, File file) throws Exception { - List params = getParams(file); - - try (ProcessRunner runner = new ProcessRunner()) { - var result = runner.exec(params); - - LOGGER.debug("command finished with stdout: {}", - result.assertExitZero(StandardCharsets.UTF_8)); - - return Files.readString(file.toPath()); - } - } - - private List getParams(File file) { - var builder = Stream. builder(); - builder.add(binaryPath); - builder.add("format"); - if (withDefaults) { - builder.add("-allowDefaults"); - } - if (configPath != null) { - builder.add("-s"); - builder.add(configPath); - } - builder.add(file.toString()); - return builder.build().collect(Collectors.toList()); - } - -} diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java index 8839bbdba0..cfe8c5f349 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java @@ -15,12 +15,31 @@ */ package com.diffplug.spotless.java; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.List; +import java.util.Objects; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.diffplug.spotless.ForeignExe; +import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.ProcessRunner; public final class IdeaStep { + private static final Logger LOGGER = LoggerFactory.getLogger(IdeaStep.class); + private IdeaStep() {} public static FormatterStep create() { @@ -38,18 +57,81 @@ public static FormatterStep create(boolean withDefaults, public static FormatterStep create(boolean withDefaults, @Nullable String binaryPath, @Nullable String configPath) { - IdeaFormatterFunc formatterFunc = getFormatterFunc(withDefaults, binaryPath, configPath); - // TODO: make it lazy - return FormatterStep.createNeverUpToDate("IDEA", formatterFunc); + return FormatterStep.createLazy("IDEA", + () -> createState(withDefaults, binaryPath, configPath), + state -> state); } - private static IdeaFormatterFunc getFormatterFunc(boolean withDefaults, + private static State createState(boolean withDefaults, @Nullable String binaryPath, @Nullable String configPath) { - if (withDefaults) { - return IdeaFormatterFunc - .allowingDefaultsWithCustomBinary(binaryPath, configPath); - } - return IdeaFormatterFunc.noDefaultsWithCustomBinary(binaryPath, configPath); + return new State(withDefaults, binaryPath, configPath); } + private static class State + implements FormatterFunc.NeedsFile, Serializable { + + private static final long serialVersionUID = -1825662355363926318L; + private static final String DEFAULT_IDEA = "idea"; + + private String binaryPath; + @Nullable + private String configPath; + private boolean withDefaults; + + private State(boolean withDefaults, @Nullable String binaryPath, + @Nullable String configPath) { + this.withDefaults = withDefaults; + this.configPath = configPath; + this.binaryPath = Objects.requireNonNullElse(binaryPath, DEFAULT_IDEA); + resolveFullBinaryPathAndCheckVersion(); + } + + private void resolveFullBinaryPathAndCheckVersion() { + var exe = ForeignExe + .nameAndVersion(this.binaryPath, "IntelliJ IDEA") + .versionRegex(Pattern.compile("(IntelliJ IDEA) .*")) + .fixCantFind( + "IDEA executable cannot be found on your machine, " + + "please install it and put idea binary to PATH; or report the problem") + .fixWrongVersion("Provided binary is not IDEA, " + + "please check it and fix the problem; or report the problem"); + try { + this.binaryPath = exe.confirmVersionAndGetAbsolutePath(); + } catch (IOException e) { + throw new IllegalArgumentException("binary cannot be found", e); + } catch (InterruptedException e) { + throw new IllegalArgumentException( + "binary cannot be found, process was interrupted", e); + } + } + + @Override + public String applyWithFile(String unix, File file) throws Exception { + List params = getParams(file); + + try (ProcessRunner runner = new ProcessRunner()) { + var result = runner.exec(params); + + LOGGER.debug("command finished with stdout: {}", + result.assertExitZero(StandardCharsets.UTF_8)); + + return Files.readString(file.toPath()); + } + } + + private List getParams(File file) { + var builder = Stream. builder(); + builder.add(binaryPath); + builder.add("format"); + if (withDefaults) { + builder.add("-allowDefaults"); + } + if (configPath != null) { + builder.add("-s"); + builder.add(configPath); + } + builder.add(file.toString()); + return builder.build().collect(Collectors.toList()); + } + } } From a0bde464fbbeb376332b6048452ec401f03f87c9 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 12 Feb 2024 16:04:52 -0800 Subject: [PATCH 12/12] spotlessApply --- .../gradle/spotless/JavaIdeaTest.java | 1 + .../diffplug/spotless/maven/java/Idea.java | 1 + .../diffplug/spotless/maven/java/Java.java | 2 +- .../spotless/maven/java/IdeaTest.java | 2 +- .../diffplug/spotless/ResourceHarness.java | 2 +- .../diffplug/spotless/java/IdeaStepTest.java | 32 +++++++++++++------ 6 files changed, 27 insertions(+), 13 deletions(-) diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java index 2e51f26bb0..b154c2d851 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/JavaIdeaTest.java @@ -18,6 +18,7 @@ import java.io.IOException; import org.junit.jupiter.api.Test; + import com.diffplug.spotless.tag.IdeaTest; @IdeaTest diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java index 83decc6867..8981a9dc9b 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java @@ -16,6 +16,7 @@ package com.diffplug.spotless.maven.java; import org.apache.maven.plugins.annotations.Parameter; + import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.java.IdeaStep; import com.diffplug.spotless.maven.FormatterStepConfig; diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java index 751da56ae9..20a2db96f7 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 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-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java index 575f88c29c..c11b2a64d1 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 DiffPlug + * Copyright 2016-2024 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/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java index fcdfa2f97d..b704d5c981 100644 --- a/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java +++ b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 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/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java b/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java index 38606c3657..98de28627a 100644 --- a/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java @@ -1,9 +1,26 @@ +/* + * Copyright 2024 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.java; import java.io.File; import java.nio.charset.StandardCharsets; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; + import com.diffplug.common.io.Files; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.ResourceHarness; @@ -24,8 +41,7 @@ void name() throws Exception { @Test void notFormattings() throws Exception { File cleanFile = newFile("clean.java"); - String cleanJava = - ResourceHarness.getTestResource("java/idea/full.clean.java"); + String cleanJava = ResourceHarness.getTestResource("java/idea/full.clean.java"); Files.write(cleanJava, cleanFile, StandardCharsets.UTF_8); FormatterStep step = IdeaStep.create(true, "idea"); @@ -38,8 +54,7 @@ void notFormattings() throws Exception { @Test void formattings() throws Exception { File dirtyFile = newFile("dirty.java"); - String dirtyJava = - ResourceHarness.getTestResource("java/idea/full.dirty.java"); + String dirtyJava = ResourceHarness.getTestResource("java/idea/full.dirty.java"); Files.write(dirtyJava, dirtyFile, StandardCharsets.UTF_8); FormatterStep step = IdeaStep.create(true, "idea"); @@ -52,8 +67,7 @@ void formattings() throws Exception { @Test void formattingsWorkWithDefaultParameters() throws Exception { File dirtyFile = newFile("dirty.java"); - String dirtyJava = - ResourceHarness.getTestResource("java/idea/full.dirty.java"); + String dirtyJava = ResourceHarness.getTestResource("java/idea/full.dirty.java"); Files.write(dirtyJava, dirtyFile, StandardCharsets.UTF_8); FormatterStep step = IdeaStep.create(); @@ -66,8 +80,7 @@ void formattingsWorkWithDefaultParameters() throws Exception { @Test void formattingsWithOutDefaultDoesNothing() throws Exception { File dirtyFile = newFile("dirty.java"); - String dirtyJava = - ResourceHarness.getTestResource("java/idea/full.dirty.java"); + String dirtyJava = ResourceHarness.getTestResource("java/idea/full.dirty.java"); Files.write(dirtyJava, dirtyFile, StandardCharsets.UTF_8); FormatterStep step = IdeaStep.create(false, "idea"); @@ -80,8 +93,7 @@ void formattingsWithOutDefaultDoesNothing() throws Exception { @Test void configureFile() throws Exception { File cleanFile = newFile("clean.java"); - String cleanJava = - ResourceHarness.getTestResource("java/idea/full.clean.java"); + String cleanJava = ResourceHarness.getTestResource("java/idea/full.clean.java"); Files.write(cleanJava, cleanFile, StandardCharsets.UTF_8); FormatterStep step = IdeaStep.create(true, "idea");