From 6419de194845da533ecfb1a0bb1afd92e07dab0e Mon Sep 17 00:00:00 2001 From: Ilya Ilyinykh Date: Thu, 11 Jan 2024 18:04:39 +0300 Subject: [PATCH 01/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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"); From 10258213c8201363b3a1b3cffd85935f98d2110f Mon Sep 17 00:00:00 2001 From: Simon Gamma Date: Mon, 16 Dec 2024 20:58:44 +0100 Subject: [PATCH 13/32] feat: add support for absolute binary path --- .../com/diffplug/spotless/java/IdeaStep.java | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) 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 cfe8c5f349..0aa3612d65 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java @@ -26,6 +26,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.slf4j.Logger; @@ -56,15 +57,15 @@ public static FormatterStep create(boolean withDefaults, } public static FormatterStep create(boolean withDefaults, - @Nullable String binaryPath, @Nullable String configPath) { + @Nullable String binaryPath, @Nullable String codeStyleSettingsPath) { return FormatterStep.createLazy("IDEA", - () -> createState(withDefaults, binaryPath, configPath), + () -> createState(withDefaults, binaryPath, codeStyleSettingsPath), state -> state); } private static State createState(boolean withDefaults, - @Nullable String binaryPath, @Nullable String configPath) { - return new State(withDefaults, binaryPath, configPath); + @Nullable String binaryPath, @Nullable String codeStyleSettingsPath) { + return new State(withDefaults, binaryPath, codeStyleSettingsPath); } private static class State @@ -75,13 +76,13 @@ private static class State private String binaryPath; @Nullable - private String configPath; + private String codeStyleSettingsPath; private boolean withDefaults; private State(boolean withDefaults, @Nullable String binaryPath, - @Nullable String configPath) { + @Nullable String codeStyleSettingsPath) { this.withDefaults = withDefaults; - this.configPath = configPath; + this.codeStyleSettingsPath = codeStyleSettingsPath; this.binaryPath = Objects.requireNonNullElse(binaryPath, DEFAULT_IDEA); resolveFullBinaryPathAndCheckVersion(); } @@ -89,10 +90,11 @@ private State(boolean withDefaults, @Nullable String binaryPath, private void resolveFullBinaryPathAndCheckVersion() { var exe = ForeignExe .nameAndVersion(this.binaryPath, "IntelliJ IDEA") + .pathToExe(pathToExe()) .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") + + "please install it and put idea binary to PATH, provide a valid path to the executable or report the problem") .fixWrongVersion("Provided binary is not IDEA, " + "please check it and fix the problem; or report the problem"); try { @@ -105,6 +107,17 @@ private void resolveFullBinaryPathAndCheckVersion() { } } + @CheckForNull + private String pathToExe() { + if (binaryPath == null) { + throw new IllegalStateException("binaryPath is not set"); + } + if (new File(binaryPath).exists()) { + return binaryPath; + } + return null; // search in PATH + } + @Override public String applyWithFile(String unix, File file) throws Exception { List params = getParams(file); @@ -126,9 +139,9 @@ private List getParams(File file) { if (withDefaults) { builder.add("-allowDefaults"); } - if (configPath != null) { + if (codeStyleSettingsPath != null) { builder.add("-s"); - builder.add(configPath); + builder.add(codeStyleSettingsPath); } builder.add(file.toString()); return builder.build().collect(Collectors.toList()); From dc3b568c893d9cb774d2f495a808c2f6a28780f5 Mon Sep 17 00:00:00 2001 From: Simon Gamma Date: Mon, 16 Dec 2024 21:07:01 +0100 Subject: [PATCH 14/32] fix: don't interact with the file directly --- .../com/diffplug/spotless/java/IdeaStep.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) 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 0aa3612d65..5c8a0597f1 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java @@ -36,6 +36,7 @@ import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.ProcessRunner; +import com.diffplug.spotless.ThrowingEx; public final class IdeaStep { @@ -120,15 +121,21 @@ private String pathToExe() { @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()); + // since we cannot directly work with the file, we need to write the unix string to a temporary file + File tempFile = File.createTempFile("spotless", file.getName()); + try { + Files.write(tempFile.toPath(), unix.getBytes(StandardCharsets.UTF_8)); + List params = getParams(tempFile); + + try (ProcessRunner runner = new ProcessRunner()) { + var result = runner.exec(params); + LOGGER.debug("command finished with stdout: {}", + result.assertExitZero(StandardCharsets.UTF_8)); + + return Files.readString(tempFile.toPath(), StandardCharsets.UTF_8); + } + } finally { + Files.delete(tempFile.toPath()); } } @@ -143,7 +150,7 @@ private List getParams(File file) { builder.add("-s"); builder.add(codeStyleSettingsPath); } - builder.add(file.toString()); + builder.add(ThrowingEx.get(file::getCanonicalPath)); return builder.build().collect(Collectors.toList()); } } From a9320dd26fa7930988c287b54badab76303a0ad4 Mon Sep 17 00:00:00 2001 From: Simon Gamma Date: Mon, 16 Dec 2024 21:11:37 +0100 Subject: [PATCH 15/32] doc: add link to jetbrains documentation --- lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java | 1 + 1 file changed, 1 insertion(+) 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 5c8a0597f1..d069e721fb 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java +++ b/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java @@ -140,6 +140,7 @@ public String applyWithFile(String unix, File file) throws Exception { } private List getParams(File file) { + /* https://www.jetbrains.com/help/idea/command-line-formatter.html */ var builder = Stream. builder(); builder.add(binaryPath); builder.add("format"); From 39d16538cab0e36323a0bf816b58dcc7f96c3768 Mon Sep 17 00:00:00 2001 From: Simon Gamma Date: Fri, 9 May 2025 20:37:46 +0200 Subject: [PATCH 16/32] refactor: move `idea` to generic formatters as it can handle various file formats besides java. --- .../spotless/{java => generic}/IdeaStep.java | 4 +- .../gradle/spotless/FormatExtension.java | 40 +++++++++++++++++++ .../gradle/spotless/JavaExtension.java | 40 ------------------- .../gradle/spotless/JavaIdeaTest.java | 2 +- .../spotless/maven/FormatterFactory.java | 7 +++- .../maven/{java => generic}/Idea.java | 6 +-- .../diffplug/spotless/maven/java/Java.java | 4 -- .../maven/{java => generic}/IdeaTest.java | 4 +- .../diffplug/spotless/ResourceHarness.java | 2 +- .../com/diffplug/spotless/tag/IdeaTest.java | 2 +- .../{java => generic}/IdeaStepTest.java | 4 +- 11 files changed, 58 insertions(+), 57 deletions(-) rename lib/src/main/java/com/diffplug/spotless/{java => generic}/IdeaStep.java (98%) rename plugin-maven/src/main/java/com/diffplug/spotless/maven/{java => generic}/Idea.java (90%) rename plugin-maven/src/test/java/com/diffplug/spotless/maven/{java => generic}/IdeaTest.java (93%) rename testlib/src/test/java/com/diffplug/spotless/{java => generic}/IdeaStepTest.java (97%) diff --git a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java similarity index 98% rename from lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java rename to lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java index d069e721fb..60f51d5d42 100644 --- a/lib/src/main/java/com/diffplug/spotless/java/IdeaStep.java +++ b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 DiffPlug + * Copyright 2024-2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.diffplug.spotless.java; +package com.diffplug.spotless.generic; import java.io.File; import java.io.IOException; diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java index 40069850c5..d60dec3af0 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java @@ -65,6 +65,7 @@ import com.diffplug.spotless.extra.wtp.EclipseWtpFormatterStep; import com.diffplug.spotless.generic.EndWithNewlineStep; import com.diffplug.spotless.generic.FenceStep; +import com.diffplug.spotless.generic.IdeaStep; import com.diffplug.spotless.generic.IndentStep; import com.diffplug.spotless.generic.LicenseHeaderStep; import com.diffplug.spotless.generic.LicenseHeaderStep.YearMode; @@ -960,6 +961,45 @@ public EclipseWtpConfig eclipseWtp(EclipseWtpFormatterStep type, String version) return new EclipseWtpConfig(type, version); } + public IdeaConfig idea() { + return new IdeaConfig(); + } + + public class IdeaConfig { + private String binaryPath; + private String configPath; + private boolean withDefaults = false; + + IdeaConfig() { + addStep(createStep()); + } + + private FormatterStep createStep() { + return IdeaStep.create(withDefaults, binaryPath, configPath); + } + + public IdeaConfig binaryPath(String binaryPath) { + requireNonNull(binaryPath); + this.binaryPath = binaryPath; + replaceStep(createStep()); + return this; + } + + public IdeaConfig configPath(String configPath) { + requireNonNull(configPath); + this.configPath = configPath; + replaceStep(createStep()); + return this; + } + + public IdeaConfig withDefaults(Boolean withDefaults) { + requireNonNull(withDefaults); + this.withDefaults = withDefaults; + replaceStep(createStep()); + return this; + } + } + /** *
 	 * spotless {
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 8440fc4d73..f0530fb968 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
@@ -38,7 +38,6 @@
 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;
@@ -358,45 +357,6 @@ public EclipseConfig withP2Mirrors(Map mirrors) {
 
 	}
 
-	public IdeaConfig idea() {
-		return new IdeaConfig();
-	}
-
-	public class IdeaConfig {
-		private String binaryPath;
-		private String configPath;
-		private boolean withDefaults = false;
-
-		IdeaConfig() {
-			addStep(createStep());
-		}
-
-		private FormatterStep createStep() {
-			return IdeaStep.create(withDefaults, binaryPath, configPath);
-		}
-
-		public IdeaConfig binaryPath(String binaryPath) {
-			Objects.requireNonNull(binaryPath);
-			this.binaryPath = binaryPath;
-			replaceStep(createStep());
-			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;
-			replaceStep(createStep());
-			return this;
-		}
-	}
-
 	/** Removes newlines between type annotations and types. */
 	public FormatAnnotationsConfig formatAnnotations() {
 		return new FormatAnnotationsConfig();
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 b154c2d851..bea9272236 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
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2024 DiffPlug
+ * Copyright 2020-2025 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/main/java/com/diffplug/spotless/maven/FormatterFactory.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java
index 456c31b9a3..143bd56e69 100644
--- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2024 DiffPlug
+ * Copyright 2016-2025 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -38,6 +38,7 @@
 import com.diffplug.spotless.LineEnding;
 import com.diffplug.spotless.maven.generic.EclipseWtp;
 import com.diffplug.spotless.maven.generic.EndWithNewline;
+import com.diffplug.spotless.maven.generic.Idea;
 import com.diffplug.spotless.maven.generic.Indent;
 import com.diffplug.spotless.maven.generic.Jsr223;
 import com.diffplug.spotless.maven.generic.LicenseHeader;
@@ -147,6 +148,10 @@ public final void addPrettier(Prettier prettier) {
 		addStepFactory(prettier);
 	}
 
+	public final void addIdea(Idea idea) {
+		addStepFactory(idea);
+	}
+
 	public final void addToggleOffOn(ToggleOffOn toggle) {
 		this.toggle = toggle;
 	}
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/generic/Idea.java
similarity index 90%
rename from plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java
rename to plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
index 8981a9dc9b..c908fe77c9 100644
--- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Idea.java
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2024 DiffPlug
+ * Copyright 2016-2025 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,12 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.diffplug.spotless.maven.java;
+package com.diffplug.spotless.maven.generic;
 
 import org.apache.maven.plugins.annotations.Parameter;
 
 import com.diffplug.spotless.FormatterStep;
-import com.diffplug.spotless.java.IdeaStep;
+import com.diffplug.spotless.generic.IdeaStep;
 import com.diffplug.spotless.maven.FormatterStepConfig;
 import com.diffplug.spotless.maven.FormatterStepFactory;
 
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 dc5de3df25..9fdb794eb1 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,10 +68,6 @@ 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/generic/IdeaTest.java
similarity index 93%
rename from plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java
rename to plugin-maven/src/test/java/com/diffplug/spotless/maven/generic/IdeaTest.java
index c11b2a64d1..c368213437 100644
--- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/IdeaTest.java
+++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/generic/IdeaTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2024 DiffPlug
+ * Copyright 2016-2025 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.diffplug.spotless.maven.java;
+package com.diffplug.spotless.maven.generic;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java b/testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java
index 0bac44952f..caf668ae8d 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-2024 DiffPlug
+ * Copyright 2016-2025 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/tag/IdeaTest.java b/testlib/src/main/java/com/diffplug/spotless/tag/IdeaTest.java
index 79813d91d9..c9f351cdcb 100644
--- a/testlib/src/main/java/com/diffplug/spotless/tag/IdeaTest.java
+++ b/testlib/src/main/java/com/diffplug/spotless/tag/IdeaTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021-2024 DiffPlug
+ * Copyright 2021-2025 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/generic/IdeaStepTest.java
similarity index 97%
rename from testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java
rename to testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
index 98de28627a..d365782db1 100644
--- a/testlib/src/test/java/com/diffplug/spotless/java/IdeaStepTest.java
+++ b/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 DiffPlug
+ * Copyright 2024-2025 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.diffplug.spotless.java;
+package com.diffplug.spotless.generic;
 
 import java.io.File;
 import java.nio.charset.StandardCharsets;

From 599ad51622d0223dbbda8f013e38959ae656f6be Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Mon, 12 May 2025 21:06:26 +0200
Subject: [PATCH 17/32] refactor: use builder for idea-step creation

---
 .../diffplug/spotless/generic/IdeaStep.java   | 99 ++++++++++++++-----
 .../gradle/spotless/FormatExtension.java      | 14 +--
 .../diffplug/spotless/maven/generic/Idea.java |  6 +-
 .../spotless/generic/IdeaStepTest.java        | 12 +--
 4 files changed, 92 insertions(+), 39 deletions(-)

diff --git a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
index 60f51d5d42..775660257f 100644
--- a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
@@ -21,12 +21,14 @@
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import org.slf4j.Logger;
@@ -40,51 +42,70 @@
 
 public final class IdeaStep {
 
+	public static final String NAME = "IDEA";
+
 	private static final Logger LOGGER = LoggerFactory.getLogger(IdeaStep.class);
 
 	private IdeaStep() {}
 
-	public static FormatterStep create() {
-		return create(true);
+	public static IdeaStepBuilder create() {
+		return new IdeaStepBuilder();
 	}
 
-	public static FormatterStep create(boolean withDefaults) {
-		return create(withDefaults, null);
+	private static FormatterStep create(@Nonnull IdeaStepBuilder builder) {
+		Objects.requireNonNull(builder);
+		return FormatterStep.createLazy(NAME,
+				() -> createState(builder),
+				state -> state);
 	}
 
-	public static FormatterStep create(boolean withDefaults,
-			@Nullable String binaryPath) {
-		return create(withDefaults, binaryPath, null);
+	private static State createState(@Nonnull IdeaStepBuilder builder) {
+		return new State(Objects.requireNonNull(builder));
 	}
 
-	public static FormatterStep create(boolean withDefaults,
-			@Nullable String binaryPath, @Nullable String codeStyleSettingsPath) {
-		return FormatterStep.createLazy("IDEA",
-				() -> createState(withDefaults, binaryPath, codeStyleSettingsPath),
-				state -> state);
-	}
+	public static final class IdeaStepBuilder {
+		private static final String DEFAULT_IDEA = "idea";
+
+		private boolean useDefaults = true;
+		@Nonnull
+		private String binaryPath = DEFAULT_IDEA;
+		@Nullable
+		private String codeStyleSettingsPath;
+
+		public IdeaStepBuilder setUseDefaults(boolean useDefaults) {
+			this.useDefaults = useDefaults;
+			return this;
+		}
+
+		public IdeaStepBuilder setBinaryPath(@Nonnull String binaryPath) {
+			this.binaryPath = Objects.requireNonNull(binaryPath);
+			return this;
+		}
+
+		public IdeaStepBuilder setCodeStyleSettingsPath(@Nullable String codeStyleSettingsPath) {
+			this.codeStyleSettingsPath = codeStyleSettingsPath;
+			return this;
+		}
 
-	private static State createState(boolean withDefaults,
-			@Nullable String binaryPath, @Nullable String codeStyleSettingsPath) {
-		return new State(withDefaults, binaryPath, codeStyleSettingsPath);
+		public FormatterStep build() {
+			return create(this);
+		}
 	}
 
 	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 codeStyleSettingsPath;
 		private boolean withDefaults;
 
-		private State(boolean withDefaults, @Nullable String binaryPath,
-				@Nullable String codeStyleSettingsPath) {
-			this.withDefaults = withDefaults;
-			this.codeStyleSettingsPath = codeStyleSettingsPath;
-			this.binaryPath = Objects.requireNonNullElse(binaryPath, DEFAULT_IDEA);
+		private State(@Nonnull IdeaStepBuilder builder) {
+			this.withDefaults = builder.useDefaults;
+			this.codeStyleSettingsPath = builder.codeStyleSettingsPath;
+			this.binaryPath = builder.binaryPath;
 			resolveFullBinaryPathAndCheckVersion();
 		}
 
@@ -113,10 +134,38 @@ private String pathToExe() {
 			if (binaryPath == null) {
 				throw new IllegalStateException("binaryPath is not set");
 			}
-			if (new File(binaryPath).exists()) {
-				return binaryPath;
+			return macOsFix(binaryPath);
+		}
+
+		@CheckForNull
+		private static String macOsFix(String binaryPath) {
+			if (!isMacOs()) {
+				if (new File(binaryPath).exists()) {
+					return binaryPath;
+				}
+				return null; // search in PATH
+			}
+			// on macOS, the binary is located in the .app bundle which might be invisible to the user
+			// we try need to append the path to the binary
+			File binary = new File(binaryPath);
+			if (!binary.exists()) {
+				// maybe it is bundle path without .app? (might be hidden by os)
+				binary = new File(binaryPath + ".app");
+				if (!binary.exists()) {
+					return binaryPath; // fallback: do nothing
+				}
+			}
+			if (binaryPath.endsWith(".app") || binary.isDirectory()) {
+				binary = new File(binary, "Contents/MacOS/idea");
 			}
-			return null; // search in PATH
+			if (binary.isFile() && binary.canExecute()) {
+				return binary.getPath();
+			}
+			return binaryPath; // fallback: do nothing
+		}
+
+		private static boolean isMacOs() {
+			return System.getProperty("os.name").toLowerCase().contains("mac");
 		}
 
 		@Override
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
index d60dec3af0..ab93e53881 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
@@ -966,35 +966,35 @@ public IdeaConfig idea() {
 	}
 
 	public class IdeaConfig {
-		private String binaryPath;
-		private String configPath;
-		private boolean withDefaults = false;
+		private final IdeaStep.IdeaStepBuilder builder;
 
 		IdeaConfig() {
+			this.builder = IdeaStep.create();
 			addStep(createStep());
 		}
 
 		private FormatterStep createStep() {
-			return IdeaStep.create(withDefaults, binaryPath, configPath);
+			return builder.build();
 		}
 
 		public IdeaConfig binaryPath(String binaryPath) {
 			requireNonNull(binaryPath);
-			this.binaryPath = binaryPath;
+			builder.setBinaryPath(binaryPath);
 			replaceStep(createStep());
 			return this;
 		}
 
+		// TODO (simschla, 11.05.2025): rename
 		public IdeaConfig configPath(String configPath) {
 			requireNonNull(configPath);
-			this.configPath = configPath;
+			builder.setCodeStyleSettingsPath(configPath);
 			replaceStep(createStep());
 			return this;
 		}
 
 		public IdeaConfig withDefaults(Boolean withDefaults) {
 			requireNonNull(withDefaults);
-			this.withDefaults = withDefaults;
+			builder.setUseDefaults(withDefaults);
 			replaceStep(createStep());
 			return this;
 		}
diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
index c908fe77c9..67a4d5b556 100644
--- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
@@ -35,6 +35,10 @@ public class Idea implements FormatterStepFactory {
 
 	@Override
 	public FormatterStep newFormatterStep(FormatterStepConfig config) {
-		return IdeaStep.create(withDefaults, binaryPath, configPath);
+		return IdeaStep.create()
+				.setUseDefaults(withDefaults)
+				.setCodeStyleSettingsPath(configPath)
+				.setBinaryPath(binaryPath)
+				.build();
 	}
 }
diff --git a/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java b/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
index d365782db1..328d9f934e 100644
--- a/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
+++ b/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
@@ -31,7 +31,7 @@ class IdeaStepTest extends ResourceHarness {
 
 	@Test
 	void name() throws Exception {
-		FormatterStep step = IdeaStep.create(true, "idea");
+		FormatterStep step = IdeaStep.create().setUseDefaults(true).setBinaryPath("idea").build();
 
 		String name = step.getName();
 
@@ -43,7 +43,7 @@ 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(true, "idea");
+		FormatterStep step = IdeaStep.create().setUseDefaults(true).setBinaryPath("/Users/simschla/Applications/IntelliJ IDEA Ultimate.app/Contents/MacOS/idea").build();
 
 		var result = step.format(cleanJava, cleanFile);
 
@@ -56,7 +56,7 @@ 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");
+		FormatterStep step = IdeaStep.create().setUseDefaults(true).setBinaryPath("/Users/simschla/Applications/IntelliJ IDEA Ultimate.app/Contents/MacOS/idea").build();
 
 		var result = step.format(dirtyJava, dirtyFile);
 
@@ -69,7 +69,7 @@ void formattingsWorkWithDefaultParameters() 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();
+		FormatterStep step = IdeaStep.create().build();
 
 		var result = step.format(dirtyJava, dirtyFile);
 
@@ -82,7 +82,7 @@ void formattingsWithOutDefaultDoesNothing() 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");
+		FormatterStep step = IdeaStep.create().setUseDefaults(false).setBinaryPath("idea").build();
 
 		var result = step.format(dirtyJava, dirtyFile);
 
@@ -95,7 +95,7 @@ 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");
+		FormatterStep step = IdeaStep.create().setUseDefaults(true).setBinaryPath("idea").build();
 
 		var result = step.format(cleanJava, cleanFile);
 

From d771a9caa0c0e821504e7cbe52640abdd5011bf7 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Tue, 13 May 2025 17:58:11 +0200
Subject: [PATCH 18/32] chore: provide custom idea.properties with custom
 config/system paths

---
 .../diffplug/spotless/generic/IdeaStep.java   | 96 +++++++++++++++----
 .../gradle/spotless/FormatExtension.java      |  2 +-
 .../diffplug/spotless/maven/generic/Idea.java |  2 +-
 .../spotless/generic/IdeaStepTest.java        | 22 +++--
 4 files changed, 96 insertions(+), 26 deletions(-)

diff --git a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
index 775660257f..066e47577f 100644
--- a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
@@ -16,13 +16,19 @@
 package com.diffplug.spotless.generic;
 
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.Serializable;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Properties;
+import java.util.TreeMap;
+import java.util.UUID;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -44,12 +50,16 @@ public final class IdeaStep {
 
 	public static final String NAME = "IDEA";
 
+	public static final String IDEA_EXECUTABLE_DEFAULT = "idea";
+
 	private static final Logger LOGGER = LoggerFactory.getLogger(IdeaStep.class);
+	public static final String IDEA_CONFIG_PATH_PROPERTY = "idea.config.path";
+	public static final String IDEA_SYSTEM_PATH_PROPERTY = "idea.system.path";
 
 	private IdeaStep() {}
 
-	public static IdeaStepBuilder create() {
-		return new IdeaStepBuilder();
+	public static IdeaStepBuilder create(@Nonnull File buildDir) {
+		return new IdeaStepBuilder(Objects.requireNonNull(buildDir));
 	}
 
 	private static FormatterStep create(@Nonnull IdeaStepBuilder builder) {
@@ -64,13 +74,20 @@ private static State createState(@Nonnull IdeaStepBuilder builder) {
 	}
 
 	public static final class IdeaStepBuilder {
-		private static final String DEFAULT_IDEA = "idea";
 
 		private boolean useDefaults = true;
 		@Nonnull
-		private String binaryPath = DEFAULT_IDEA;
+		private String binaryPath = IDEA_EXECUTABLE_DEFAULT;
 		@Nullable
 		private String codeStyleSettingsPath;
+		private final Map ideaProperties = new HashMap<>();
+
+		@Nonnull
+		private final File buildDir;
+
+		private IdeaStepBuilder(@Nonnull File buildDir) {
+			this.buildDir = Objects.requireNonNull(buildDir);
+		}
 
 		public IdeaStepBuilder setUseDefaults(boolean useDefaults) {
 			this.useDefaults = useDefaults;
@@ -87,6 +104,14 @@ public IdeaStepBuilder setCodeStyleSettingsPath(@Nullable String codeStyleSettin
 			return this;
 		}
 
+		public IdeaStepBuilder setIdeaProperties(@Nonnull Map ideaProperties) {
+			if (ideaProperties.containsKey(IDEA_CONFIG_PATH_PROPERTY) || ideaProperties.containsKey(IDEA_SYSTEM_PATH_PROPERTY)) {
+				throw new IllegalArgumentException("Cannot override IDEA config or system path");
+			}
+			this.ideaProperties.putAll(ideaProperties);
+			return this;
+		}
+
 		public FormatterStep build() {
 			return create(this);
 		}
@@ -97,22 +122,27 @@ private static class State
 
 		private static final long serialVersionUID = -1825662355363926318L;
 
-		private String binaryPath;
+		private final String buildDir;
+		private final String uniquePath;
+		private final String binaryPath;
 		@Nullable
-		private String codeStyleSettingsPath;
-		private boolean withDefaults;
+		private final String codeStyleSettingsPath; // TODO make sure to save content in state
+		private final boolean withDefaults;
+		private final TreeMap ideaProperties;
 
 		private State(@Nonnull IdeaStepBuilder builder) {
+			this.buildDir = ThrowingEx.get(builder.buildDir::getCanonicalPath);
+			this.uniquePath = UUID.randomUUID().toString();
 			this.withDefaults = builder.useDefaults;
 			this.codeStyleSettingsPath = builder.codeStyleSettingsPath;
-			this.binaryPath = builder.binaryPath;
-			resolveFullBinaryPathAndCheckVersion();
+			this.ideaProperties = new TreeMap<>(builder.ideaProperties);
+			this.binaryPath = resolveFullBinaryPathAndCheckVersion(builder.binaryPath);
 		}
 
-		private void resolveFullBinaryPathAndCheckVersion() {
+		private static String resolveFullBinaryPathAndCheckVersion(String binaryPath) {
 			var exe = ForeignExe
-					.nameAndVersion(this.binaryPath, "IntelliJ IDEA")
-					.pathToExe(pathToExe())
+					.nameAndVersion(binaryPath, "IntelliJ IDEA")
+					.pathToExe(pathToExe(binaryPath))
 					.versionRegex(Pattern.compile("(IntelliJ IDEA) .*"))
 					.fixCantFind(
 							"IDEA executable cannot be found on your machine, "
@@ -120,7 +150,7 @@ private void resolveFullBinaryPathAndCheckVersion() {
 					.fixWrongVersion("Provided binary is not IDEA, "
 							+ "please check it and fix the problem; or report the problem");
 			try {
-				this.binaryPath = exe.confirmVersionAndGetAbsolutePath();
+				return exe.confirmVersionAndGetAbsolutePath();
 			} catch (IOException e) {
 				throw new IllegalArgumentException("binary cannot be found", e);
 			} catch (InterruptedException e) {
@@ -130,10 +160,7 @@ private void resolveFullBinaryPathAndCheckVersion() {
 		}
 
 		@CheckForNull
-		private String pathToExe() {
-			if (binaryPath == null) {
-				throw new IllegalStateException("binaryPath is not set");
-			}
+		private static String pathToExe(String binaryPath) {
 			return macOsFix(binaryPath);
 		}
 
@@ -177,7 +204,8 @@ public String applyWithFile(String unix, File file) throws Exception {
 				List params = getParams(tempFile);
 
 				try (ProcessRunner runner = new ProcessRunner()) {
-					var result = runner.exec(params);
+					Map env = createEnv();
+					var result = runner.exec(null, env, null, params);
 					LOGGER.debug("command finished with stdout: {}",
 							result.assertExitZero(StandardCharsets.UTF_8));
 
@@ -188,6 +216,38 @@ public String applyWithFile(String unix, File file) throws Exception {
 			}
 		}
 
+		private Map createEnv() {
+			File ideaProps = createIdeaPropertiesFile();
+			Map env = Map.ofEntries(
+					Map.entry("IDEA_PROPERTIES", ThrowingEx.get(ideaProps::getCanonicalPath)));
+			return env;
+		}
+
+		private File createIdeaPropertiesFile() {
+			Path ideaProps = new File(buildDir).toPath().resolve(uniquePath).resolve("idea.properties");
+
+			if (Files.exists(ideaProps)) {
+				return ideaProps.toFile(); // only create if it does not exist
+			}
+
+			ThrowingEx.run(() -> Files.createDirectories(ideaProps.getParent()));
+
+			Path configPath = ideaProps.getParent().resolve("config");
+			Path systemPath = ideaProps.getParent().resolve("system");
+
+			Properties properties = new Properties();
+			properties.putAll(ideaProperties);
+			properties.put(IDEA_CONFIG_PATH_PROPERTY, ThrowingEx.get(configPath.toFile()::getCanonicalPath));
+			properties.put(IDEA_SYSTEM_PATH_PROPERTY, ThrowingEx.get(systemPath.toFile()::getCanonicalPath));
+
+			try (FileOutputStream out = new FileOutputStream(ideaProps.toFile())) {
+				properties.store(out, "Generated by spotless");
+			} catch (IOException e) {
+				throw new IllegalStateException("Failed to create IDEA properties file", e);
+			}
+			return ideaProps.toFile();
+		}
+
 		private List getParams(File file) {
 			/* https://www.jetbrains.com/help/idea/command-line-formatter.html */
 			var builder = Stream. builder();
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
index ab93e53881..b1f8cb9d6b 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
@@ -969,7 +969,7 @@ public class IdeaConfig {
 		private final IdeaStep.IdeaStepBuilder builder;
 
 		IdeaConfig() {
-			this.builder = IdeaStep.create();
+			this.builder = IdeaStep.create(getProject().getLayout().getBuildDirectory().getAsFile().get());
 			addStep(createStep());
 		}
 
diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
index 67a4d5b556..ab9de41a08 100644
--- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
@@ -35,7 +35,7 @@ public class Idea implements FormatterStepFactory {
 
 	@Override
 	public FormatterStep newFormatterStep(FormatterStepConfig config) {
-		return IdeaStep.create()
+		return IdeaStep.create(config.getFileLocator().getBuildDir())
 				.setUseDefaults(withDefaults)
 				.setCodeStyleSettingsPath(configPath)
 				.setBinaryPath(binaryPath)
diff --git a/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java b/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
index 328d9f934e..05b643805e 100644
--- a/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
+++ b/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
@@ -24,6 +24,7 @@
 import com.diffplug.common.io.Files;
 import com.diffplug.spotless.FormatterStep;
 import com.diffplug.spotless.ResourceHarness;
+import com.diffplug.spotless.ThrowingEx;
 import com.diffplug.spotless.tag.IdeaTest;
 
 @IdeaTest
@@ -31,7 +32,7 @@ class IdeaStepTest extends ResourceHarness {
 
 	@Test
 	void name() throws Exception {
-		FormatterStep step = IdeaStep.create().setUseDefaults(true).setBinaryPath("idea").build();
+		FormatterStep step = IdeaStep.create(buildDir()).setUseDefaults(true).build();
 
 		String name = step.getName();
 
@@ -43,7 +44,7 @@ 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().setUseDefaults(true).setBinaryPath("/Users/simschla/Applications/IntelliJ IDEA Ultimate.app/Contents/MacOS/idea").build();
+		FormatterStep step = IdeaStep.create(buildDir()).setUseDefaults(true).build();
 
 		var result = step.format(cleanJava, cleanFile);
 
@@ -56,7 +57,7 @@ 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().setUseDefaults(true).setBinaryPath("/Users/simschla/Applications/IntelliJ IDEA Ultimate.app/Contents/MacOS/idea").build();
+		FormatterStep step = IdeaStep.create(buildDir()).setUseDefaults(true).build();
 
 		var result = step.format(dirtyJava, dirtyFile);
 
@@ -69,7 +70,7 @@ void formattingsWorkWithDefaultParameters() 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().build();
+		FormatterStep step = IdeaStep.create(buildDir()).build();
 
 		var result = step.format(dirtyJava, dirtyFile);
 
@@ -82,7 +83,7 @@ void formattingsWithOutDefaultDoesNothing() 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().setUseDefaults(false).setBinaryPath("idea").build();
+		FormatterStep step = IdeaStep.create(buildDir()).setUseDefaults(false).build();
 
 		var result = step.format(dirtyJava, dirtyFile);
 
@@ -95,11 +96,20 @@ 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().setUseDefaults(true).setBinaryPath("idea").build();
+		FormatterStep step = IdeaStep.create(buildDir()).setUseDefaults(true).build();
 
 		var result = step.format(cleanJava, cleanFile);
 
 		Assertions.assertEquals(cleanJava, result,
 				"formatting was applied to clean file");
 	}
+
+	private File buildDir = null;
+
+	protected File buildDir() {
+		if (this.buildDir == null) {
+			this.buildDir = ThrowingEx.get(() -> newFolder("build-dir"));
+		}
+		return this.buildDir;
+	}
 }

From 619051c723ff4428251496ccf22b828a0f203014 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Tue, 13 May 2025 20:18:22 +0200
Subject: [PATCH 19/32] chore: fix formatter to use UTF-8 (as asserted by
 spotless)

---
 lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
index 066e47577f..7c76bb8aa1 100644
--- a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
@@ -260,6 +260,7 @@ private List getParams(File file) {
 				builder.add("-s");
 				builder.add(codeStyleSettingsPath);
 			}
+			builder.add("-charset").add("UTF-8");
 			builder.add(ThrowingEx.get(file::getCanonicalPath));
 			return builder.build().collect(Collectors.toList());
 		}

From 0570c6af0575664bac88951418ac6c4aff3c0bdc Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Tue, 13 May 2025 21:08:39 +0200
Subject: [PATCH 20/32] feat: allow specifying idea execs not on path

---
 .gitignore                                    |  1 +
 gradle/special-tests.gradle                   |  4 +
 .../diffplug/spotless/generic/IdeaStep.java   | 19 ++--
 .../spotless/generic/TestEnvVars.java         | 93 +++++++++++++++++++
 4 files changed, 110 insertions(+), 7 deletions(-)
 create mode 100644 lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java

diff --git a/.gitignore b/.gitignore
index 2f8c81aca6..28ce16fa21 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
 # Project-specific stuff
 userHome/
 workspace/
+testenv.properties
 
 ### Gradle ###
 .gradle
diff --git a/gradle/special-tests.gradle b/gradle/special-tests.gradle
index 29295b19ec..1931043e42 100644
--- a/gradle/special-tests.gradle
+++ b/gradle/special-tests.gradle
@@ -38,5 +38,9 @@ tasks.named('test').configure {
 special.forEach { tag ->
 	tasks.register("test${tag.capitalize()}", Test) {
 		useJUnitPlatform { includeTags tag }
+		if (rootProject.file('testenv.properties').exists()) {
+			systemProperty 'testenv.properties.path', rootProject.file('testenv.properties').canonicalPath
+		}
 	}
 }
+
diff --git a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
index 7c76bb8aa1..b758b0e6d4 100644
--- a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
@@ -161,17 +161,22 @@ private static String resolveFullBinaryPathAndCheckVersion(String binaryPath) {
 
 		@CheckForNull
 		private static String pathToExe(String binaryPath) {
-			return macOsFix(binaryPath);
+			String testEnvBinaryPath = TestEnvVars.read().get(String.format("%s.%s", IdeaStep.class.getName(), "binaryPath"));
+			if (testEnvBinaryPath != null) {
+				return testEnvBinaryPath;
+			}
+			if (isMacOs()) {
+				return macOsFix(binaryPath);
+			}
+			if (new File(binaryPath).exists()) {
+				return binaryPath;
+			}
+			return null; // search in PATH
 		}
 
 		@CheckForNull
 		private static String macOsFix(String binaryPath) {
-			if (!isMacOs()) {
-				if (new File(binaryPath).exists()) {
-					return binaryPath;
-				}
-				return null; // search in PATH
-			}
+
 			// on macOS, the binary is located in the .app bundle which might be invisible to the user
 			// we try need to append the path to the binary
 			File binary = new File(binaryPath);
diff --git a/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java b/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java
new file mode 100644
index 0000000000..c0966c511f
--- /dev/null
+++ b/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2025 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.generic;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import javax.annotation.Nullable;
+
+class TestEnvVars {
+
+	private final Map envVars;
+
+	private static TestEnvVars INSTANCE;
+
+	private TestEnvVars(Map envVars) {
+		this.envVars = Map.copyOf(envVars);
+	}
+
+	public static synchronized TestEnvVars read() {
+		if (INSTANCE == null) {
+			INSTANCE = new TestEnvVars(readTestEnvVars());
+		}
+		return INSTANCE;
+	}
+
+	private static Map readTestEnvVars() {
+		Map envVars = new HashMap<>();
+		Optional resolvedTestenvProps = candidateTestEnvLocations().filter(Files::exists).findFirst();
+		resolvedTestenvProps.ifPresent(testenvProps -> {
+			try (var reader = Files.newBufferedReader(testenvProps)) {
+				java.util.Properties properties = new java.util.Properties();
+				properties.load(reader);
+				for (String name : properties.stringPropertyNames()) {
+					envVars.put(name, properties.getProperty(name));
+				}
+			} catch (IOException e) {
+				throw new RuntimeException("Failed to read test environment variables", e);
+			}
+		});
+		return envVars;
+	}
+
+	private static Stream candidateTestEnvLocations() {
+		Stream.Builder builder = Stream.builder();
+		if (System.getProperty("testenv.properties.path") != null) {
+			builder.add(Path.of(System.getProperty("testenv.properties.path")));
+		}
+		builder.add(
+				Path.of(System.getProperty("user.dir"), "testenv.properties"));
+		builder.add(
+				Path.of(System.getProperty("user.dir")).getParent().resolve("testenv.properties"));
+		return builder.build();
+	}
+
+	public @Nullable String get(String key) {
+		return envVars.get(key);
+	}
+
+	public String getOrDefault(String key, String defaultValue) {
+		return envVars.getOrDefault(key, defaultValue);
+	}
+
+	public String getOrThrow(String key) {
+		String value = envVars.get(key);
+		if (value == null) {
+			throw new IllegalArgumentException("Environment variable " + key + " not found");
+		}
+		return value;
+	}
+
+	public boolean hasKey(String key) {
+		return envVars.containsKey(key);
+	}
+}

From 1027acacaf7196a8d61beeb49111620ab98ad63c Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Fri, 16 May 2025 20:49:35 +0200
Subject: [PATCH 21/32] refactor: turn ideastep into autoclosable
 implementation

---
 .../diffplug/spotless/generic/IdeaStep.java   | 73 +++++++++++++------
 1 file changed, 51 insertions(+), 22 deletions(-)

diff --git a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
index b758b0e6d4..7adbd12762 100644
--- a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
@@ -65,8 +65,7 @@ public static IdeaStepBuilder create(@Nonnull File buildDir) {
 	private static FormatterStep create(@Nonnull IdeaStepBuilder builder) {
 		Objects.requireNonNull(builder);
 		return FormatterStep.createLazy(NAME,
-				() -> createState(builder),
-				state -> state);
+				() -> createState(builder), State::toFunc);
 	}
 
 	private static State createState(@Nonnull IdeaStepBuilder builder) {
@@ -117,22 +116,19 @@ public FormatterStep build() {
 		}
 	}
 
-	private static class State
-			implements FormatterFunc.NeedsFile, Serializable {
+	private static class State implements Serializable {
 
-		private static final long serialVersionUID = -1825662355363926318L;
+		private static final long serialVersionUID = -1426311255869303398L;
 
-		private final String buildDir;
-		private final String uniquePath;
+		private final File uniqueBuildFolder;
 		private final String binaryPath;
 		@Nullable
-		private final String codeStyleSettingsPath; // TODO make sure to save content in state
+		private final String codeStyleSettingsPath;
 		private final boolean withDefaults;
 		private final TreeMap ideaProperties;
 
 		private State(@Nonnull IdeaStepBuilder builder) {
-			this.buildDir = ThrowingEx.get(builder.buildDir::getCanonicalPath);
-			this.uniquePath = UUID.randomUUID().toString();
+			this.uniqueBuildFolder = new File(builder.buildDir, UUID.randomUUID().toString());
 			this.withDefaults = builder.useDefaults;
 			this.codeStyleSettingsPath = builder.codeStyleSettingsPath;
 			this.ideaProperties = new TreeMap<>(builder.ideaProperties);
@@ -174,7 +170,6 @@ private static String pathToExe(String binaryPath) {
 			return null; // search in PATH
 		}
 
-		@CheckForNull
 		private static String macOsFix(String binaryPath) {
 
 			// on macOS, the binary is located in the .app bundle which might be invisible to the user
@@ -200,22 +195,18 @@ private static boolean isMacOs() {
 			return System.getProperty("os.name").toLowerCase().contains("mac");
 		}
 
-		@Override
-		public String applyWithFile(String unix, File file) throws Exception {
+		private String format(IdeaStepFormatterCleanupResources ideaStepFormatterCleanupResources, String unix, File file) throws Exception {
 			// since we cannot directly work with the file, we need to write the unix string to a temporary file
 			File tempFile = File.createTempFile("spotless", file.getName());
 			try {
 				Files.write(tempFile.toPath(), unix.getBytes(StandardCharsets.UTF_8));
 				List params = getParams(tempFile);
 
-				try (ProcessRunner runner = new ProcessRunner()) {
-					Map env = createEnv();
-					var result = runner.exec(null, env, null, params);
-					LOGGER.debug("command finished with stdout: {}",
-							result.assertExitZero(StandardCharsets.UTF_8));
-
-					return Files.readString(tempFile.toPath(), StandardCharsets.UTF_8);
-				}
+				Map env = createEnv();
+				var result = ideaStepFormatterCleanupResources.runner.exec(null, env, null, params);
+				LOGGER.debug("command finished with stdout: {}",
+						result.assertExitZero(StandardCharsets.UTF_8));
+				return Files.readString(tempFile.toPath(), StandardCharsets.UTF_8);
 			} finally {
 				Files.delete(tempFile.toPath());
 			}
@@ -229,7 +220,7 @@ private Map createEnv() {
 		}
 
 		private File createIdeaPropertiesFile() {
-			Path ideaProps = new File(buildDir).toPath().resolve(uniquePath).resolve("idea.properties");
+			Path ideaProps = this.uniqueBuildFolder.toPath().resolve("idea.properties");
 
 			if (Files.exists(ideaProps)) {
 				return ideaProps.toFile(); // only create if it does not exist
@@ -269,5 +260,43 @@ private List getParams(File file) {
 			builder.add(ThrowingEx.get(file::getCanonicalPath));
 			return builder.build().collect(Collectors.toList());
 		}
+
+		private FormatterFunc.Closeable toFunc() {
+			IdeaStepFormatterCleanupResources ideaStepFormatterCleanupResources = new IdeaStepFormatterCleanupResources(uniqueBuildFolder, new ProcessRunner());
+			return FormatterFunc.Closeable.of(ideaStepFormatterCleanupResources, this::format);
+		}
+	}
+
+	private static class IdeaStepFormatterCleanupResources implements AutoCloseable {
+		@Nonnull
+		private final File uniqueBuildFolder;
+		@Nonnull
+		private final ProcessRunner runner;
+
+		public IdeaStepFormatterCleanupResources(@Nonnull File uniqueBuildFolder, @Nonnull ProcessRunner runner) {
+			this.uniqueBuildFolder = uniqueBuildFolder;
+			this.runner = runner;
+		}
+
+		@Override
+		public void close() throws Exception {
+			// close the runner
+			runner.close();
+			// delete the unique build folder
+			if (uniqueBuildFolder.exists()) {
+				// delete the unique build folder recursively
+				try (Stream paths = Files.walk(uniqueBuildFolder.toPath())) {
+					paths.sorted((o1, o2) -> o2.compareTo(o1)) // delete files first
+							.forEach(path -> {
+								try {
+									Files.delete(path);
+								} catch (IOException e) {
+									LOGGER.warn("Failed to delete file: {}", path, e);
+								}
+							});
+				}
+			}
+		}
+
 	}
 }

From 7b2b21cc66feabaca446d506d079d557d624be75 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Sun, 18 May 2025 21:40:54 +0200
Subject: [PATCH 22/32] refactor: adapt creation pipeline to allow createLazy
 to work with function pointers

---
 .../diffplug/spotless/generic/IdeaStep.java   | 38 +++++++++++++++----
 .../gradle/spotless/FormatExtension.java      |  2 +-
 .../diffplug/spotless/maven/generic/Idea.java |  2 +-
 .../spotless/generic/IdeaStepTest.java        | 12 +++---
 4 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
index 7adbd12762..fd975e4df4 100644
--- a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
@@ -48,27 +48,34 @@
 
 public final class IdeaStep {
 
+	private static final Logger LOGGER = LoggerFactory.getLogger(IdeaStep.class);
+
 	public static final String NAME = "IDEA";
 
 	public static final String IDEA_EXECUTABLE_DEFAULT = "idea";
 
-	private static final Logger LOGGER = LoggerFactory.getLogger(IdeaStep.class);
 	public static final String IDEA_CONFIG_PATH_PROPERTY = "idea.config.path";
 	public static final String IDEA_SYSTEM_PATH_PROPERTY = "idea.system.path";
+	@Nonnull
+	private final IdeaStepBuilder builder;
 
-	private IdeaStep() {}
+	private IdeaStep(@Nonnull IdeaStepBuilder builder) {
+		this.builder = builder;
+	}
 
-	public static IdeaStepBuilder create(@Nonnull File buildDir) {
+	public static IdeaStepBuilder newBuilder(@Nonnull File buildDir) {
 		return new IdeaStepBuilder(Objects.requireNonNull(buildDir));
 	}
 
-	private static FormatterStep create(@Nonnull IdeaStepBuilder builder) {
-		Objects.requireNonNull(builder);
-		return FormatterStep.createLazy(NAME,
-				() -> createState(builder), State::toFunc);
+	private static FormatterStep create(IdeaStepBuilder builder) {
+		return new IdeaStep(builder).createFormatterStep();
 	}
 
-	private static State createState(@Nonnull IdeaStepBuilder builder) {
+	private FormatterStep createFormatterStep() {
+		return FormatterStep.createLazy(NAME, this::createState, State::toFunc);
+	}
+
+	private State createState() {
 		return new State(Objects.requireNonNull(builder));
 	}
 
@@ -114,6 +121,17 @@ public IdeaStepBuilder setIdeaProperties(@Nonnull Map ideaProper
 		public FormatterStep build() {
 			return create(this);
 		}
+
+		@Override
+		public String toString() {
+			return String.format(
+					"IdeaStepBuilder[useDefaults=%s, binaryPath=%s, codeStyleSettingsPath=%s, ideaProperties=%s, buildDir=%s]",
+					this.useDefaults,
+					this.binaryPath,
+					this.codeStyleSettingsPath,
+					this.ideaProperties,
+					this.buildDir);
+		}
 	}
 
 	private static class State implements Serializable {
@@ -128,6 +146,7 @@ private static class State implements Serializable {
 		private final TreeMap ideaProperties;
 
 		private State(@Nonnull IdeaStepBuilder builder) {
+			LOGGER.debug("Creating {} state with configuration {}", NAME, builder);
 			this.uniqueBuildFolder = new File(builder.buildDir, UUID.randomUUID().toString());
 			this.withDefaults = builder.useDefaults;
 			this.codeStyleSettingsPath = builder.codeStyleSettingsPath;
@@ -203,7 +222,9 @@ private String format(IdeaStepFormatterCleanupResources ideaStepFormatterCleanup
 				List params = getParams(tempFile);
 
 				Map env = createEnv();
+				LOGGER.info("Launching IDEA formatter for orig file {} with params: {} and env: {}", file, params, env);
 				var result = ideaStepFormatterCleanupResources.runner.exec(null, env, null, params);
+				LOGGER.debug("command finished with exit code: {}", result.exitCode());
 				LOGGER.debug("command finished with stdout: {}",
 						result.assertExitZero(StandardCharsets.UTF_8));
 				return Files.readString(tempFile.toPath(), StandardCharsets.UTF_8);
@@ -236,6 +257,7 @@ private File createIdeaPropertiesFile() {
 			properties.put(IDEA_CONFIG_PATH_PROPERTY, ThrowingEx.get(configPath.toFile()::getCanonicalPath));
 			properties.put(IDEA_SYSTEM_PATH_PROPERTY, ThrowingEx.get(systemPath.toFile()::getCanonicalPath));
 
+			LOGGER.debug("Creating IDEA properties file at {} with content: {}", ideaProps, properties);
 			try (FileOutputStream out = new FileOutputStream(ideaProps.toFile())) {
 				properties.store(out, "Generated by spotless");
 			} catch (IOException e) {
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
index b1f8cb9d6b..f457500ee7 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
@@ -969,7 +969,7 @@ public class IdeaConfig {
 		private final IdeaStep.IdeaStepBuilder builder;
 
 		IdeaConfig() {
-			this.builder = IdeaStep.create(getProject().getLayout().getBuildDirectory().getAsFile().get());
+			this.builder = IdeaStep.newBuilder(getProject().getLayout().getBuildDirectory().getAsFile().get());
 			addStep(createStep());
 		}
 
diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
index ab9de41a08..0e09b8f1a7 100644
--- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
@@ -35,7 +35,7 @@ public class Idea implements FormatterStepFactory {
 
 	@Override
 	public FormatterStep newFormatterStep(FormatterStepConfig config) {
-		return IdeaStep.create(config.getFileLocator().getBuildDir())
+		return IdeaStep.newBuilder(config.getFileLocator().getBuildDir())
 				.setUseDefaults(withDefaults)
 				.setCodeStyleSettingsPath(configPath)
 				.setBinaryPath(binaryPath)
diff --git a/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java b/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
index 05b643805e..fad95e10f4 100644
--- a/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
+++ b/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
@@ -32,7 +32,7 @@ class IdeaStepTest extends ResourceHarness {
 
 	@Test
 	void name() throws Exception {
-		FormatterStep step = IdeaStep.create(buildDir()).setUseDefaults(true).build();
+		FormatterStep step = IdeaStep.newBuilder(buildDir()).setUseDefaults(true).build();
 
 		String name = step.getName();
 
@@ -44,7 +44,7 @@ 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(buildDir()).setUseDefaults(true).build();
+		FormatterStep step = IdeaStep.newBuilder(buildDir()).setUseDefaults(true).build();
 
 		var result = step.format(cleanJava, cleanFile);
 
@@ -57,7 +57,7 @@ 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(buildDir()).setUseDefaults(true).build();
+		FormatterStep step = IdeaStep.newBuilder(buildDir()).setUseDefaults(true).build();
 
 		var result = step.format(dirtyJava, dirtyFile);
 
@@ -70,7 +70,7 @@ void formattingsWorkWithDefaultParameters() 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(buildDir()).build();
+		FormatterStep step = IdeaStep.newBuilder(buildDir()).build();
 
 		var result = step.format(dirtyJava, dirtyFile);
 
@@ -83,7 +83,7 @@ void formattingsWithOutDefaultDoesNothing() 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(buildDir()).setUseDefaults(false).build();
+		FormatterStep step = IdeaStep.newBuilder(buildDir()).setUseDefaults(false).build();
 
 		var result = step.format(dirtyJava, dirtyFile);
 
@@ -96,7 +96,7 @@ 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(buildDir()).setUseDefaults(true).build();
+		FormatterStep step = IdeaStep.newBuilder(buildDir()).setUseDefaults(true).build();
 
 		var result = step.format(cleanJava, cleanFile);
 

From 412430deb47dd0126e90bef6d37d686244663513 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Mon, 19 May 2025 21:01:25 +0200
Subject: [PATCH 23/32] chore: add testIdea to ci

---
 .github/workflows/ci.yml | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e5de52b4d9..051f9802c5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -59,6 +59,9 @@ jobs:
             jre: 11
             os: ubuntu-latest
             shfmt-version: v3.8.0
+          - kind: idea
+            jre: 11
+            os: ubuntu-latest
     runs-on: ${{ matrix.os }}
     steps:
       - name: Checkout
@@ -91,6 +94,16 @@ jobs:
       - name: Test shfmt
         if: matrix.kind == 'shfmt'
         run: ./gradlew testShfmt
+      - name: Test idea
+        if: matrix.kind == 'idea'
+        run: |
+          download_link=$(curl https://data.services.jetbrains.com/products/releases\?code\=IIC\&latest\=true\&type\=release | jq -r '.IIC[0].downloads.linux.link')
+          curl --location "$download_link" -o idea.tar.gz
+          tar -xf idea.tar.gz
+          cd idea-IC*
+          export PATH=${PATH}:$(pwd)/bin
+          cd ..
+          ./gradlew testIdea
       - name: junit result
         uses: mikepenz/action-junit-report@v5
         if: always() # always run even if the previous step fails

From b686a1c56248314dfeedeed94a012c167fca9773 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Fri, 20 Jun 2025 21:40:41 +0200
Subject: [PATCH 24/32] docs: start documenting idea usage

---
 plugin-gradle/README.md | 42 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md
index 7a2c6b42b7..148f01bcce 100644
--- a/plugin-gradle/README.md
+++ b/plugin-gradle/README.md
@@ -55,7 +55,7 @@ Spotless supports all of Gradle's built-in performance features (incremental bui
   - [Requirements](#requirements)
   - [Linting](#linting)
 - **Languages**
-  - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [clang-format](#clang-format), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat))
+  - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [clang-format](#clang-format), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [IntelliJ IDEA](#intellij-idea))
   - [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy))
   - [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [prettier](#prettier))
   - [Scala](#scala) ([scalafmt](#scalafmt))
@@ -65,7 +65,7 @@ Spotless supports all of Gradle's built-in performance features (incremental bui
   - [FreshMark](#freshmark) aka markdown
   - [Flexmark](#flexmark) aka markdown
   - [Antlr4](#antlr4) ([antlr4formatter](#antlr4formatter))
-  - [SQL](#sql) ([dbeaver](#dbeaver), [prettier](#prettier))
+  - [SQL](#sql) ([dbeaver](#dbeaver), [prettier](#prettier), [IntelliJ IDEA](#intellij-idea))
   - [Maven POM](#maven-pom) ([sortPom](#sortpom))
   - [Typescript](#typescript) ([tsfmt](#tsfmt), [prettier](#prettier), [ESLint](#eslint-typescript), [Biome](#biome))
   - [Javascript](#javascript) ([prettier](#prettier), [ESLint](#eslint-javascript), [Biome](#biome))
@@ -78,6 +78,7 @@ Spotless supports all of Gradle's built-in performance features (incremental bui
     - [clang-format](#clang-format)
     - [eclipse web tools platform](#eclipse-web-tools-platform)
     - [Biome](#biome) ([binary detection](#biome-binary), [config file](#biome-configuration-file), [input language](#biome-input-language))
+    - [IntelliJ IDEA](#intellij-idea)
 - **Language independent**
   - [Generic steps](#generic-steps)
   - [License header](#license-header) ([slurp year from git](#retroactively-slurp-years-from-git-history))
@@ -198,6 +199,7 @@ spotless {
     eclipse()            // has its own section below
     prettier()           // has its own section below
     clangFormat()        // has its own section below
+    idea()               // has its own section below
 
     formatAnnotations()  // fixes formatting of type annotations, see below
 
@@ -754,6 +756,7 @@ spotless {
 
     dbeaver()  // has its own section below
     prettier() // has its own section below
+    idea()     // has its own section below
   }
 }
 ```
@@ -1581,9 +1584,42 @@ The following languages are currently recognized:
 * `ts?` -- TypeScript, with or without JSX, depending on the file extension
 * `json` -- JSON
 
+## IntelliJ IDEA
+
+[homepage](https://www.jetbrains.com/idea/). [changelog](https://www.jetbrains.com/idea/whatsnew/). 
+
+`IntelliJ IDEA` is a powerful IDE for java, kotlin and many more languages. There are [specific variants](https://www.jetbrains.com/products/) for almost any modern language
+and a plethora of [plugins](https://plugins.jetbrains.com/).
+
+Spotless provides access to IntelliJ IDEA's command line formatter. 
+
+
+```gradle
+spotless {
+  format 'myFormatter', {
+    // you have to set the target manually
+    target 'src/main/**/*.java','jbang/*.java'
+
+    idea()
+      .codeStyleSettingsPath('/path/to/config') // if you have custom formatting rules, see below for how to get them
+      .withDefaults(true) // Use the default code style settings when the code style is not defined for a file type (default: true)
+
+    // if idea is not on your path, you must specify the path to the executable
+    idea().binaryPath('/path/to/idea')
+  }
+}
+```
+
+### How to generate code style settings files
+TODO
+
+### Limitations
+- Currently, only IntelliJ IDEA is supported - none of the other jetbrains IDE. Consider opening a PR if you want to change this.
+- Launching IntelliJ IDEA from the command line is pretty expensive and as of now, we do this for each file. If you want to change this, consider opening a PR.
+
 ## Generic steps
 
-[Prettier](#prettier), [eclipse wtp](#eclipse-web-tools-platform), and [license header](#license-header) are available in every format, and they each have their own section. As mentioned in the [quickstart](#quickstart), there are a variety of simple generic steps which are also available in every format, here are examples of these:
+[Prettier](#prettier), [eclipse wtp](#eclipse-web-tools-platform), [IntelliJ IDEA](#intellij-idea) and [license header](#license-header) are available in every format, and they each have their own section. As mentioned in the [quickstart](#quickstart), there are a variety of simple generic steps which are also available in every format, here are examples of these:
 
 ```gradle
 spotless {

From 3277660331bf2945ccf8e786461410d12b7f37c1 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Fri, 20 Jun 2025 21:40:58 +0200
Subject: [PATCH 25/32] chore: adapt api for idea step

---
 .../java/com/diffplug/gradle/spotless/FormatExtension.java     | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
index f457500ee7..3b96a85394 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
@@ -984,8 +984,7 @@ public IdeaConfig binaryPath(String binaryPath) {
 			return this;
 		}
 
-		// TODO (simschla, 11.05.2025): rename
-		public IdeaConfig configPath(String configPath) {
+		public IdeaConfig codeStyleSettingsPath(String configPath) {
 			requireNonNull(configPath);
 			builder.setCodeStyleSettingsPath(configPath);
 			replaceStep(createStep());

From 6d71e4d594528ad13a15a4a5f7d07fe7c78d3e60 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Wed, 25 Jun 2025 20:17:02 +0200
Subject: [PATCH 26/32] docs: add documentation for IntelliJ codestyle

---
 INTELLIJ_IDEA_SCREENSHOTS.md          |  16 +++++++++
 _images/intellij_export_codestyle.png | Bin 0 -> 133848 bytes
 plugin-gradle/README.md               |   7 ++--
 plugin-maven/README.md                |  49 +++++++++++++++++++++++---
 4 files changed, 64 insertions(+), 8 deletions(-)
 create mode 100644 INTELLIJ_IDEA_SCREENSHOTS.md
 create mode 100644 _images/intellij_export_codestyle.png

diff --git a/INTELLIJ_IDEA_SCREENSHOTS.md b/INTELLIJ_IDEA_SCREENSHOTS.md
new file mode 100644
index 0000000000..31e264b5ea
--- /dev/null
+++ b/INTELLIJ_IDEA_SCREENSHOTS.md
@@ -0,0 +1,16 @@
+# Extracting Code Style from IntelliJ IDEA
+
+## 1. Exporting Code Style Settings to a file
+To export code style settings from IntelliJ IDEA to a file, go to
+`Settings | Editor | Code Style` and click on the gear icon next to the scheme name.
+
+![Exporting code style settings](_images/intellij_export_codestyle.png)
+
+## 2. Using IntelliJ's active code style directly
+If you have your code style settings checked into version control (in your `.idea` directory), 
+you can use the active code style directly in Spotless without exporting it to a file. 
+The file can be found at `.idea/codeStyles/Project.xml`.
+
+## Upstream documentation
+More details can be found in the [IntelliJ IDEA documentation](https://www.jetbrains.com/help/idea/command-line-formatter.html#options)
+for the command line formatter, which is what Spotless uses under the hood.
diff --git a/_images/intellij_export_codestyle.png b/_images/intellij_export_codestyle.png
new file mode 100644
index 0000000000000000000000000000000000000000..e0c98d2cdbd1b987c118a1ebeabc536fc6d1d1a8
GIT binary patch
literal 133848
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
P2=LKX*HtT1wSMwHd2Wgy

literal 0
HcmV?d00001

diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md
index 148f01bcce..f775bf58a8 100644
--- a/plugin-gradle/README.md
+++ b/plugin-gradle/README.md
@@ -1593,7 +1593,6 @@ and a plethora of [plugins](https://plugins.jetbrains.com/).
 
 Spotless provides access to IntelliJ IDEA's command line formatter. 
 
-
 ```gradle
 spotless {
   format 'myFormatter', {
@@ -1601,8 +1600,8 @@ spotless {
     target 'src/main/**/*.java','jbang/*.java'
 
     idea()
-      .codeStyleSettingsPath('/path/to/config') // if you have custom formatting rules, see below for how to get them
-      .withDefaults(true) // Use the default code style settings when the code style is not defined for a file type (default: true)
+      .codeStyleSettingsPath('/path/to/config') // if you have custom formatting rules, see below for how to extract/reference them
+      .withDefaults(false) // Disable using default code style settings when no custom code style is defined for a file type (default: true)
 
     // if idea is not on your path, you must specify the path to the executable
     idea().binaryPath('/path/to/idea')
@@ -1611,7 +1610,7 @@ spotless {
 ```
 
 ### How to generate code style settings files
-TODO
+See [here](../INTELLIJ_IDEA_SCREENSHOTS.md) for an explanation on how to extract or reference existing code style files. 
 
 ### Limitations
 - Currently, only IntelliJ IDEA is supported - none of the other jetbrains IDE. Consider opening a PR if you want to change this.
diff --git a/plugin-maven/README.md b/plugin-maven/README.md
index b27ddc4eab..b6c238940c 100644
--- a/plugin-maven/README.md
+++ b/plugin-maven/README.md
@@ -38,15 +38,15 @@ user@machine repo % mvn spotless:check
 - [**Quickstart**](#quickstart)
   - [Requirements](#requirements)
   - [Binding to maven phase](#binding-to-maven-phase)
-- **Languages**
-  - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat))
+- **Languages** // TODO add idea
+  - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat),[IntelliiJ IDEA](#intellij-idea))
   - [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy))
   - [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [prettier](#prettier))
   - [Scala](#scala) ([scalafmt](#scalafmt))
   - [C/C++](#cc) ([eclipse cdt](#eclipse-cdt), [clang-format](#clang-format))
   - [Python](#python) ([black](#black))
   - [Antlr4](#antlr4) ([antlr4formatter](#antlr4formatter))
-  - [Sql](#sql) ([dbeaver](#dbeaver))
+  - [Sql](#sql) ([dbeaver](#dbeaver), [prettier](#prettier), [IntelliJ IDEA](#intellij-idea))
   - [Maven Pom](#maven-pom) ([sortPom](#sortpom))
   - [Markdown](#markdown) ([flexmark](#flexmark))
   - [Typescript](#typescript) ([tsfmt](#tsfmt), [prettier](#prettier), [ESLint](#eslint-typescript), [Biome](#biome))
@@ -61,6 +61,7 @@ user@machine repo % mvn spotless:check
     - [Prettier](#prettier) ([plugins](#prettier-plugins), [npm detection](#npm-detection), [`.npmrc` detection](#npmrc-detection), [caching `npm install` results](#caching-results-of-npm-install))
     - [eclipse web tools platform](#eclipse-web-tools-platform)
     - [Biome](#biome) ([binary detection](#biome-binary), [config file](#biome-configuration-file), [input language](#biome-input-language))
+    - [IntelliJ IDEA](#intellij-idea)
 - **Language independent**
   - [Generic steps](#generic-steps)
   - [License header](#license-header) ([slurp year from git](#retroactively-slurp-years-from-git-history))
@@ -194,6 +195,7 @@ any other maven phase (i.e. compile) then it can be configured as below;
      
               
              
+                 
 
      
       
@@ -665,6 +667,7 @@ Additionally, `editorConfigOverride` options will override what's supplied in `.
 
       
      
+         
   
 
 ```
@@ -1666,9 +1669,47 @@ The following languages are currently recognized:
 * `ts?` -- TypeScript, with or without JSX, depending on the file extension
 * `json` -- JSON
 
+## IntelliJ IDEA
+
+[homepage](https://www.jetbrains.com/idea/). [changelog](https://www.jetbrains.com/idea/whatsnew/).
+
+`IntelliJ IDEA` is a powerful IDE for java, kotlin and many more languages. There are [specific variants](https://www.jetbrains.com/products/) for almost any modern language
+and a plethora of [plugins](https://plugins.jetbrains.com/).
+
+Spotless provides access to IntelliJ IDEA's command line formatter.
+
+```xml
+
+  
+    
+      
+        src/main/**/*.java
+        jbang/*.java
+      
+
+      
+        
+        /path/to/config
+        
+        false
+        
+        /path/to/idea
+      
+    
+  
+
+```
+
+### How to generate code style settings files
+See [here](../INTELLIJ_IDEA_SCREENSHOTS.md) for an explanation on how to extract or reference existing code style files.
+
+### Limitations
+- Currently, only IntelliJ IDEA is supported - none of the other jetbrains IDE. Consider opening a PR if you want to change this.
+- Launching IntelliJ IDEA from the command line is pretty expensive and as of now, we do this for each file. If you want to change this, consider opening a PR.
+
 ## Generic steps
 
-[Prettier](#prettier), [eclipse wtp](#eclipse-web-tools-platform), and [license header](#license-header) are available in every format, and they each have their own section. As mentioned in the [quickstart](#quickstart), there are a variety of simple generic steps which are also available in every format, here are examples of these:
+[Prettier](#prettier), [eclipse wtp](#eclipse-web-tools-platform), [IntelliJ IDEA](#intellij-idea) and [license header](#license-header) are available in every format, and they each have their own section. As mentioned in the [quickstart](#quickstart), there are a variety of simple generic steps which are also available in every format, here are examples of these:
 
 ```xml
  

From 50e2589256943684356134261a17970411877e6e Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Wed, 25 Jun 2025 21:24:49 +0200
Subject: [PATCH 27/32] fix(mvn): pass developer root dir to maven tests

---
 .../spotless/generic/TestEnvVars.java         |  3 +++
 plugin-maven/build.gradle                     |  1 +
 .../diffplug/spotless/maven/generic/Idea.java |  6 ++---
 .../maven/MavenIntegrationHarness.java        | 10 +++++--
 .../diffplug/spotless/maven/MavenRunner.java  | 26 +++++++++++++++++--
 5 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java b/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java
index c0966c511f..f341f09b99 100644
--- a/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java
+++ b/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java
@@ -64,6 +64,9 @@ private static Stream candidateTestEnvLocations() {
 		if (System.getProperty("testenv.properties.path") != null) {
 			builder.add(Path.of(System.getProperty("testenv.properties.path")));
 		}
+		if (System.getProperty("spotlessProjectDir") != null) {
+			builder.add(Path.of(System.getProperty("spotlessProjectDir"), "testenv.properties"));
+		}
 		builder.add(
 				Path.of(System.getProperty("user.dir"), "testenv.properties"));
 		builder.add(
diff --git a/plugin-maven/build.gradle b/plugin-maven/build.gradle
index 7932d4a007..d8e5f90770 100644
--- a/plugin-maven/build.gradle
+++ b/plugin-maven/build.gradle
@@ -55,6 +55,7 @@ dependencies {
 apply from: rootProject.file('gradle/special-tests.gradle')
 tasks.withType(Test).configureEach {
 	systemProperty 'spotlessMavenPluginVersion', project.version
+	systemProperty 'spotlessProjectDir', "${project.rootProject.projectDir}".toString()
 	dependsOn 'publishToMavenLocal'
 	dependsOn ':lib:publishToMavenLocal'
 	dependsOn ':lib-extra:publishToMavenLocal'
diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
index 0e09b8f1a7..2c3b5587a3 100644
--- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
+++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Idea.java
@@ -28,16 +28,16 @@ public class Idea implements FormatterStepFactory {
 	private String binaryPath;
 
 	@Parameter
-	private String configPath;
+	private String codeStyleSettingsPath;
 
 	@Parameter
-	private Boolean withDefaults = false;
+	private Boolean withDefaults = true;
 
 	@Override
 	public FormatterStep newFormatterStep(FormatterStepConfig config) {
 		return IdeaStep.newBuilder(config.getFileLocator().getBuildDir())
 				.setUseDefaults(withDefaults)
-				.setCodeStyleSettingsPath(configPath)
+				.setCodeStyleSettingsPath(codeStyleSettingsPath)
 				.setBinaryPath(binaryPath)
 				.build();
 	}
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 0d0582e180..f3e1f30355 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
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2024 DiffPlug
+ * Copyright 2016-2025 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -213,9 +213,15 @@ protected void writePom(String[] executions, String[] configuration, String[] de
 	}
 
 	protected MavenRunner mavenRunner() throws IOException {
-		return MavenRunner.create()
+		MavenRunner mavenRunner = MavenRunner.create()
 				.withProjectDir(rootFolder())
 				.withRunner(runner);
+		System.getProperties().forEach((key, value) -> {
+			if (key instanceof String && ((String) key).startsWith("spotless") && value instanceof String) {
+				mavenRunner.withSystemProperty((String) key, (String) value);
+			}
+		});
+		return mavenRunner;
 	}
 
 	private static ProcessRunner runner;
diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenRunner.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenRunner.java
index c8d845f8a2..6e22fe5e31 100644
--- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenRunner.java
+++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/MavenRunner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2023 DiffPlug
+ * Copyright 2016-2025 DiffPlug
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import com.diffplug.spotless.Jvm;
 import com.diffplug.spotless.ProcessRunner;
@@ -41,6 +43,7 @@ private MavenRunner() {}
 	private File projectDir;
 	private String[] args;
 	private Map environment = new HashMap<>();
+	private Map systemProperties = new HashMap<>();
 	private ProcessRunner runner;
 
 	public MavenRunner withProjectDir(File projectDir) {
@@ -64,12 +67,31 @@ public MavenRunner withRemoteDebug(int port) {
 		return this;
 	}
 
+	public MavenRunner withSystemProperty(String key, String value) {
+		systemProperties.put(key, value);
+		return this;
+	}
+
+	private Map calculateEnvironment() {
+		Map env = new HashMap<>(environment);
+		if (!systemProperties.isEmpty()) {
+			// add system properties as environment variables as MAVEN_OPTS or append if already there
+			String sysProps = systemProperties.entrySet().stream()
+					.map(entry -> String.format("-D%s=%s", entry.getKey(), entry.getValue()))
+					.collect(Collectors.joining(" "));
+			String mavenOpts = Stream.of(env.getOrDefault("MAVEN_OPTS", ""), sysProps)
+					.collect(Collectors.joining(" "));
+			env.put("MAVEN_OPTS", mavenOpts.trim());
+		}
+		return env;
+	}
+
 	private ProcessRunner.Result run() throws IOException, InterruptedException {
 		Objects.requireNonNull(projectDir, "Need to call withProjectDir() first");
 		Objects.requireNonNull(args, "Need to call withArguments() first");
 		// run Maven with the given args in the given directory
 		String argsString = "-e " + String.join(" ", Arrays.asList(args));
-		return runner.shellWinUnix(projectDir, environment, "mvnw " + argsString, "./mvnw " + argsString);
+		return runner.shellWinUnix(projectDir, calculateEnvironment(), "mvnw " + argsString, "./mvnw " + argsString);
 	}
 
 	/** Runs the command and asserts that exit code is 0. */

From 3000ad8fcf38428b89ce4c2403446251720a04f0 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Sun, 29 Jun 2025 20:51:02 +0200
Subject: [PATCH 28/32] style: reformat with spotless

---
 .../diffplug/spotless/generic/IdeaStep.java   |  7 ++----
 .../gradle/spotless/FormatExtension.java      | 24 +++++++------------
 2 files changed, 10 insertions(+), 21 deletions(-)

diff --git a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
index fd975e4df4..e14e975cb5 100644
--- a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
@@ -84,8 +84,7 @@ public static final class IdeaStepBuilder {
 		private boolean useDefaults = true;
 		@Nonnull
 		private String binaryPath = IDEA_EXECUTABLE_DEFAULT;
-		@Nullable
-		private String codeStyleSettingsPath;
+		@Nullable private String codeStyleSettingsPath;
 		private final Map ideaProperties = new HashMap<>();
 
 		@Nonnull
@@ -140,8 +139,7 @@ private static class State implements Serializable {
 
 		private final File uniqueBuildFolder;
 		private final String binaryPath;
-		@Nullable
-		private final String codeStyleSettingsPath;
+		@Nullable private final String codeStyleSettingsPath;
 		private final boolean withDefaults;
 		private final TreeMap ideaProperties;
 
@@ -190,7 +188,6 @@ private static String pathToExe(String binaryPath) {
 		}
 
 		private static String macOsFix(String binaryPath) {
-
 			// on macOS, the binary is located in the .app bundle which might be invisible to the user
 			// we try need to append the path to the binary
 			File binary = new File(binaryPath);
diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
index 3b96a85394..1216b15864 100644
--- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
+++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java
@@ -218,8 +218,7 @@ public void encoding(String charset) {
 	protected FileCollection target, targetExclude;
 
 	/** The value from which files will be excluded if their content contain it. */
-	@Nullable
-	protected String targetExcludeContentPattern = null;
+	@Nullable protected String targetExcludeContentPattern = null;
 
 	protected boolean isLicenseHeaderStep(FormatterStep formatterStep) {
 		String formatterStepName = formatterStep.getName();
@@ -687,17 +686,13 @@ public abstract static class NpmStepConfig> {
 
 		public static final String SPOTLESS_NPM_INSTALL_CACHE_DEFAULT_NAME = "spotless-npm-install-cache";
 
-		@Nullable
-		protected Object npmFile;
+		@Nullable protected Object npmFile;
 
-		@Nullable
-		protected Object nodeFile;
+		@Nullable protected Object nodeFile;
 
-		@Nullable
-		protected Object npmInstallCache;
+		@Nullable protected Object npmInstallCache;
 
-		@Nullable
-		protected Object npmrcFile;
+		@Nullable protected Object npmrcFile;
 
 		protected Project project;
 
@@ -771,11 +766,9 @@ protected void replaceStep() {
 
 	public class PrettierConfig extends NpmStepConfig {
 
-		@Nullable
-		Object prettierConfigFile;
+		@Nullable Object prettierConfigFile;
 
-		@Nullable
-		Map prettierConfig;
+		@Nullable Map prettierConfig;
 
 		final Map devDependencies;
 
@@ -815,8 +808,7 @@ protected FormatterStep createStep() {
 	 * format{ ... }.
 	 */
 	public class BiomeGeneric extends BiomeStepConfig {
-		@Nullable
-		String language;
+		@Nullable String language;
 
 		/**
 		 * Creates a new Biome config that downloads the Biome executable for the given

From b7aed375c0be85b27a1d9774f50f683b58e92767 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Sun, 29 Jun 2025 20:51:13 +0200
Subject: [PATCH 29/32] docs: update with PR-reference

---
 CHANGES.md               | 2 +-
 plugin-gradle/CHANGES.md | 2 +-
 plugin-maven/CHANGES.md  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 2d82b3c711..938e3c385c 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -11,7 +11,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
 
 ## [Unreleased]
 ### Added
-* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020))
+* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020), [#2535](https://github.com/diffplug/spotless/pull/2535))
 * Add support for removing wildcard imports via `removeWildcardImports` step. ([#2517](https://github.com/diffplug/spotless/pull/2517))
 
 ## [3.1.2] - 2025-05-27
diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md
index e5c37e06a1..121d9d922c 100644
--- a/plugin-gradle/CHANGES.md
+++ b/plugin-gradle/CHANGES.md
@@ -4,7 +4,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
 
 ## [Unreleased]
 ### Added
-* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020))
+* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020), [#2535](https://github.com/diffplug/spotless/pull/2535))
 * Add support for removing wildcard imports via `removeWildcardImports` step. ([#2517](https://github.com/diffplug/spotless/pull/2517))
 
 ## [7.0.4] - 2025-05-27
diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md
index 06d09cc81d..cab00b07af 100644
--- a/plugin-maven/CHANGES.md
+++ b/plugin-maven/CHANGES.md
@@ -4,7 +4,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
 
 ## [Unreleased]
 ### Added
-* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020))
+* Support for `idea` ([#2020](https://github.com/diffplug/spotless/pull/2020), [#2535](https://github.com/diffplug/spotless/pull/2535))
 * Add support for removing wildcard imports via `removeWildcardImports` step. ([#2517](https://github.com/diffplug/spotless/pull/2517))
 
 ## [2.44.5] - 2025-05-27

From b5e117eb56264c8225f86f871969b2b54e2b8742 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Mon, 30 Jun 2025 08:16:23 +0200
Subject: [PATCH 30/32] fix: correct pmd warnings

---
 .../com/diffplug/spotless/generic/IdeaStep.java     | 13 +++++++++----
 .../com/diffplug/spotless/generic/TestEnvVars.java  |  3 ++-
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
index e14e975cb5..209a0d7560 100644
--- a/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
+++ b/lib/src/main/java/com/diffplug/spotless/generic/IdeaStep.java
@@ -24,6 +24,7 @@
 import java.nio.file.Path;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Properties;
@@ -208,7 +209,7 @@ private static String macOsFix(String binaryPath) {
 		}
 
 		private static boolean isMacOs() {
-			return System.getProperty("os.name").toLowerCase().contains("mac");
+			return System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("mac");
 		}
 
 		private String format(IdeaStepFormatterCleanupResources ideaStepFormatterCleanupResources, String unix, File file) throws Exception {
@@ -244,10 +245,14 @@ private File createIdeaPropertiesFile() {
 				return ideaProps.toFile(); // only create if it does not exist
 			}
 
-			ThrowingEx.run(() -> Files.createDirectories(ideaProps.getParent()));
+			Path parent = ideaProps.getParent();
+			if (parent == null) {
+				throw new IllegalStateException(String.format("Parent directory for IDEA properties file %s cannot be null", ideaProps));
+			}
+			ThrowingEx.run(() -> Files.createDirectories(parent));
 
-			Path configPath = ideaProps.getParent().resolve("config");
-			Path systemPath = ideaProps.getParent().resolve("system");
+			Path configPath = parent.resolve("config");
+			Path systemPath = parent.resolve("system");
 
 			Properties properties = new Properties();
 			properties.putAll(ideaProperties);
diff --git a/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java b/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java
index f341f09b99..8845fe9c0d 100644
--- a/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java
+++ b/lib/src/main/java/com/diffplug/spotless/generic/TestEnvVars.java
@@ -20,6 +20,7 @@
 import java.nio.file.Path;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Stream;
 
@@ -70,7 +71,7 @@ private static Stream candidateTestEnvLocations() {
 		builder.add(
 				Path.of(System.getProperty("user.dir"), "testenv.properties"));
 		builder.add(
-				Path.of(System.getProperty("user.dir")).getParent().resolve("testenv.properties"));
+				Objects.requireNonNull(Path.of(System.getProperty("user.dir")).getParent()).resolve("testenv.properties"));
 		return builder.build();
 	}
 

From 044f98d88486f6c492927f6725109bacea051131 Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Mon, 30 Jun 2025 16:25:08 +0200
Subject: [PATCH 31/32] docs: fix typo

---
 plugin-maven/README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/plugin-maven/README.md b/plugin-maven/README.md
index b6c238940c..212e16e48a 100644
--- a/plugin-maven/README.md
+++ b/plugin-maven/README.md
@@ -39,7 +39,7 @@ user@machine repo % mvn spotless:check
   - [Requirements](#requirements)
   - [Binding to maven phase](#binding-to-maven-phase)
 - **Languages** // TODO add idea
-  - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat),[IntelliiJ IDEA](#intellij-idea))
+  - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [IntelliJ IDEA](#intellij-idea))
   - [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy))
   - [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [prettier](#prettier))
   - [Scala](#scala) ([scalafmt](#scalafmt))

From 6c7ecf5322dfa6d04f952a4e4f96d05504ceedde Mon Sep 17 00:00:00 2001
From: Simon Gamma 
Date: Mon, 30 Jun 2025 16:26:46 +0200
Subject: [PATCH 32/32] chore: cleanups based on review

---
 plugin-maven/README.md                                          | 2 +-
 .../test/java/com/diffplug/spotless/generic/IdeaStepTest.java   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/plugin-maven/README.md b/plugin-maven/README.md
index 212e16e48a..2e5839e819 100644
--- a/plugin-maven/README.md
+++ b/plugin-maven/README.md
@@ -38,7 +38,7 @@ user@machine repo % mvn spotless:check
 - [**Quickstart**](#quickstart)
   - [Requirements](#requirements)
   - [Binding to maven phase](#binding-to-maven-phase)
-- **Languages** // TODO add idea
+- **Languages**
   - [Java](#java) ([google-java-format](#google-java-format), [eclipse jdt](#eclipse-jdt), [prettier](#prettier), [palantir-java-format](#palantir-java-format), [formatAnnotations](#formatAnnotations), [cleanthat](#cleanthat), [IntelliJ IDEA](#intellij-idea))
   - [Groovy](#groovy) ([eclipse groovy](#eclipse-groovy))
   - [Kotlin](#kotlin) ([ktfmt](#ktfmt), [ktlint](#ktlint), [diktat](#diktat), [prettier](#prettier))
diff --git a/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java b/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
index fad95e10f4..299ea4e45f 100644
--- a/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
+++ b/testlib/src/test/java/com/diffplug/spotless/generic/IdeaStepTest.java
@@ -79,7 +79,7 @@ void formattingsWorkWithDefaultParameters() throws Exception {
 	}
 
 	@Test
-	void formattingsWithOutDefaultDoesNothing() throws Exception {
+	void formattingsWithoutDefaultDoesNothing() throws Exception {
 		File dirtyFile = newFile("dirty.java");
 		String dirtyJava = ResourceHarness.getTestResource("java/idea/full.dirty.java");
 		Files.write(dirtyJava, dirtyFile, StandardCharsets.UTF_8);