From 4dd5b5fb616e82cb09c329458edaee019219b092 Mon Sep 17 00:00:00 2001 From: Dimitrii Lipiridi Date: Wed, 16 Aug 2023 23:10:53 +0300 Subject: [PATCH 1/8] feat: Introduce "spotlessIdeHook" argument for maven plugin --- plugin-maven/CHANGES.md | 1 + plugin-maven/README.md | 15 ++++++++++++--- .../spotless/maven/AbstractSpotlessMojo.java | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 65a557b14f..62d0f8c500 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -6,6 +6,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ### Added * Add a `jsonPatch` step to `json` formatter configurations. This allows patching of JSON documents using [JSON Patches](https://jsonpatch.com). ([#1753](https://github.com/diffplug/spotless/pull/1753)) * Support GJF own import order. ([#1780](https://github.com/diffplug/spotless/pull/1780)) +* `-DspotlessIdeHook` provides the ability to apply Spotless exclusively to a specified file. It accepts the absolute path of the file. ### Fixed * Add support for `prettier` version `3.0.0` and newer. ([#1760]https://github.com/diffplug/spotless/pull/1760), [#1751](https://github.com/diffplug/spotless/issues/1751)) * Fix npm install calls when npm cache is not up-to-date. ([#1760]https://github.com/diffplug/spotless/pull/1760), [#1750](https://github.com/diffplug/spotless/issues/1750)) diff --git a/plugin-maven/README.md b/plugin-maven/README.md index cb770099ac..aa324627f9 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -1601,14 +1601,23 @@ By default, `spotless:check` is bound to the `verify` phase. You might want to ## Can I apply Spotless to specific files? -You can target specific files by setting the `spotlessFiles` project property to a comma-separated list of file patterns: +There are two options: +### Pattern +You can target specific files by setting the `spotlessFiles` project property to a comma-separated list of file patterns: ``` -cmd> mvn spotless:apply -DspotlessFiles=my/file/pattern.java,more/generic/.*-pattern.java +cmd> mvn spotless:apply -DspotlessFiles="my/file/pattern\.java, more/generic/.*-pattern\.java" ``` - The patterns are matched using `String#matches(String)` against the absolute file path. +### IDE Hook +You can specify a single file by providing the `spotlessIdeHook` argument, which accepts the absolute path of the file. +``` +cmd> mvn spotless:apply -DspotlessIdeHook="C:\my-project\src\main\java\com\example\Application.java" + +``` +This option ignores the ratchetFrom property. + ## Example configurations (from real-world projects) diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index 2c295cef27..ea66e921e5 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -187,6 +187,9 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo { @Parameter(property = "spotlessFiles") private String filePatterns; + @Parameter(property = "spotlessIdeHook") + private String spotlessIdeHook; + @Parameter(property = LicenseHeaderStep.spotlessSetLicenseHeaderYearsFromGitHistory) private String setLicenseHeaderYearsFromGitHistory; @@ -251,6 +254,10 @@ private boolean shouldSkip() { } private List collectFiles(FormatterFactory formatterFactory, FormatterConfig config) { + if (!(spotlessIdeHook == null || spotlessIdeHook.isEmpty())) { + return fetchFileFromIdeHook(); + } + Optional ratchetFrom = formatterFactory.ratchetFrom(config); try { final List files; @@ -279,6 +286,15 @@ private List collectFiles(FormatterFactory formatterFactory, FormatterConf } } + private List fetchFileFromIdeHook() { + File file = new File(spotlessIdeHook); + if (!file.isAbsolute()) { + throw new PluginException("Argument passed to spotlessIdeHook must be an absolute path"); + } + + return List.of(file); + } + private List collectFilesFromGit(FormatterFactory formatterFactory, String ratchetFrom) { MatchPatterns includePatterns = MatchPatterns.from( withNormalizedFileSeparators(getIncludes(formatterFactory))); From b83d1de4dd231eba868919d2c9662ddbdad51f06 Mon Sep 17 00:00:00 2001 From: Dimitrii Lipiridi Date: Thu, 17 Aug 2023 19:12:08 +0300 Subject: [PATCH 2/8] fix: Update example of spotlessFiles argument --- 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 aa324627f9..956dbf385e 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -1606,7 +1606,7 @@ There are two options: ### Pattern You can target specific files by setting the `spotlessFiles` project property to a comma-separated list of file patterns: ``` -cmd> mvn spotless:apply -DspotlessFiles="my/file/pattern\.java, more/generic/.*-pattern\.java" +cmd> mvn spotless:apply -DspotlessFiles="src.main.java.com.example.*, .+Config.*\.java" ``` The patterns are matched using `String#matches(String)` against the absolute file path. From cb5cb6adc6306d3673a64370f4f1920d6626cde6 Mon Sep 17 00:00:00 2001 From: Dimitrii Lipiridi Date: Thu, 17 Aug 2023 21:28:23 +0300 Subject: [PATCH 3/8] feat: Add issue link to CHANGES.md --- plugin-maven/CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 62d0f8c500..972e0bf6e2 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -6,7 +6,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ### Added * Add a `jsonPatch` step to `json` formatter configurations. This allows patching of JSON documents using [JSON Patches](https://jsonpatch.com). ([#1753](https://github.com/diffplug/spotless/pull/1753)) * Support GJF own import order. ([#1780](https://github.com/diffplug/spotless/pull/1780)) -* `-DspotlessIdeHook` provides the ability to apply Spotless exclusively to a specified file. It accepts the absolute path of the file. +* Add `-DspotlessIdeHook` that provides the ability to apply Spotless exclusively to a specified file. It accepts the absolute path of the file. ([#200](https://github.com/diffplug/spotless/issues/200)) ### Fixed * Add support for `prettier` version `3.0.0` and newer. ([#1760]https://github.com/diffplug/spotless/pull/1760), [#1751](https://github.com/diffplug/spotless/issues/1751)) * Fix npm install calls when npm cache is not up-to-date. ([#1760]https://github.com/diffplug/spotless/pull/1760), [#1750](https://github.com/diffplug/spotless/issues/1750)) From 1d6b717c44f8d25e3b33936e280a06428c143a55 Mon Sep 17 00:00:00 2001 From: Dimitrii Lipiridi Date: Sun, 20 Aug 2023 21:31:08 +0300 Subject: [PATCH 4/8] feat: Prepare Maven's IDE hook --- .../gradle/spotless/FormatExtension.java | 2 +- plugin-maven/build.gradle | 1 + .../spotless/maven/AbstractSpotlessMojo.java | 36 +++----- .../com/diffplug/spotless/maven/IdeHook.java | 87 +++++++++++++++++++ .../spotless/maven/SpotlessApplyMojo.java | 31 +++++++ 5 files changed, 132 insertions(+), 25 deletions(-) create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/IdeHook.java 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 7a62f8cabf..0e4e4395c3 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 @@ -124,7 +124,7 @@ public void setEncoding(String name) { /** @see #setRatchetFrom(String) */ public String getRatchetFrom() { - return ratchetFrom == RATCHETFROM_NOT_SET_AT_FORMAT_LEVEL ? spotless.getRatchetFrom() : ratchetFrom; + return ratchetFrom.equals(RATCHETFROM_NOT_SET_AT_FORMAT_LEVEL) ? spotless.getRatchetFrom() : ratchetFrom; } /** diff --git a/plugin-maven/build.gradle b/plugin-maven/build.gradle index 7cfb38c2e9..74a76ddcb1 100644 --- a/plugin-maven/build.gradle +++ b/plugin-maven/build.gradle @@ -39,6 +39,7 @@ dependencies { compileOnly "org.eclipse.aether:aether-api:${VER_ECLIPSE_AETHER}" implementation "com.diffplug.durian:durian-core:${VER_DURIAN}" + implementation "com.diffplug.durian:durian-io:${VER_DURIAN}" implementation "com.diffplug.durian:durian-collect:${VER_DURIAN}" implementation("org.codehaus.plexus:plexus-resources:${VER_PLEXUS_RESOURCES}") implementation "org.eclipse.jgit:org.eclipse.jgit:${VER_JGIT}" diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index ea66e921e5..825859716f 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -187,9 +187,6 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo { @Parameter(property = "spotlessFiles") private String filePatterns; - @Parameter(property = "spotlessIdeHook") - private String spotlessIdeHook; - @Parameter(property = LicenseHeaderStep.spotlessSetLicenseHeaderYearsFromGitHistory) private String setLicenseHeaderYearsFromGitHistory; @@ -254,10 +251,6 @@ private boolean shouldSkip() { } private List collectFiles(FormatterFactory formatterFactory, FormatterConfig config) { - if (!(spotlessIdeHook == null || spotlessIdeHook.isEmpty())) { - return fetchFileFromIdeHook(); - } - Optional ratchetFrom = formatterFactory.ratchetFrom(config); try { final List files; @@ -271,30 +264,21 @@ private List collectFiles(FormatterFactory formatterFactory, FormatterConf } final String[] includePatterns = this.filePatterns.split(","); final List compiledIncludePatterns = Arrays.stream(includePatterns) - .map(Pattern::compile) - .collect(Collectors.toList()); + .map(Pattern::compile) + .collect(Collectors.toList()); final Predicate shouldInclude = file -> compiledIncludePatterns - .stream() - .anyMatch(filePattern -> filePattern.matcher(file.getAbsolutePath()) - .matches()); + .stream() + .anyMatch(filePattern -> filePattern.matcher(file.getAbsolutePath()) + .matches()); return files - .stream() - .filter(shouldInclude) - .collect(toList()); + .stream() + .filter(shouldInclude) + .collect(toList()); } catch (IOException e) { throw new PluginException("Unable to scan file tree rooted at " + baseDir, e); } } - private List fetchFileFromIdeHook() { - File file = new File(spotlessIdeHook); - if (!file.isAbsolute()) { - throw new PluginException("Argument passed to spotlessIdeHook must be an absolute path"); - } - - return List.of(file); - } - private List collectFilesFromGit(FormatterFactory formatterFactory, String ratchetFrom) { MatchPatterns includePatterns = MatchPatterns.from( withNormalizedFileSeparators(getIncludes(formatterFactory))); @@ -400,4 +384,8 @@ private UpToDateChecker createUpToDateChecker(Iterable formatters) { } return UpToDateChecker.wrapWithBuildContext(checker, buildContext); } + + protected File getBaseDir() { + return baseDir; + } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/IdeHook.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/IdeHook.java new file mode 100644 index 0000000000..dba9bcc547 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/IdeHook.java @@ -0,0 +1,87 @@ +/* + * 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; + +import com.diffplug.common.base.Errors; +import com.diffplug.common.io.ByteStreams; +import com.diffplug.spotless.Formatter; +import com.diffplug.spotless.PaddedCell; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.List; + +class IdeHook { + + private static void dumpIsClean() { + System.err.println("IS CLEAN"); + } + + static void performHook(Iterable projectFiles, String path, Formatter formatter, File projectDir, String ratchetFrom, boolean spotlessIdeHookUseStdIn, boolean spotlessIdeHookUseStdOut) { + File file = new File(path); + if (!file.isAbsolute()) { + System.err.println("Argument passed to spotlessIdeHook must be an absolute path"); + return; + } + if (projectContainsFile(projectFiles, file)) { + try { + if (ratchetFrom != null) { + GitRatchetMaven ratchet = GitRatchetMaven.instance(); + if (ratchet.isClean(projectDir, ratchet.rootTreeShaOf(projectDir, ratchetFrom), file)) { + dumpIsClean(); + return; + } + } + byte[] bytes; + if (spotlessIdeHookUseStdIn) { + bytes = ByteStreams.toByteArray(System.in); + } else { + bytes = Files.readAllBytes(file.toPath()); + } + PaddedCell.DirtyState dirty = PaddedCell.calculateDirtyState(formatter, file, bytes); + if (dirty.isClean()) { + dumpIsClean(); + } else if (dirty.didNotConverge()) { + System.err.println("DID NOT CONVERGE"); + System.err.println("Run 'spotlessDiagnose' for details https://github.com/diffplug/spotless/blob/main/PADDEDCELL.md"); + } else { + System.err.println("IS DIRTY"); + if (spotlessIdeHookUseStdOut) { + dirty.writeCanonicalTo(System.out); + } else { + dirty.writeCanonicalTo(file); + } + } + } catch (IOException e) { + e.printStackTrace(System.err); + throw Errors.asRuntime(e); + } finally { + System.err.close(); + System.out.close(); + } + } + } + + private static boolean projectContainsFile(Iterable projectFiles, File file) { + for (File projectFile : projectFiles) { + if (projectFile.equals(file)) { + return true; + } + } + return false; + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java index 5ebe2885c9..9d5e3f9b14 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java @@ -18,6 +18,8 @@ import java.io.File; import java.io.IOException; +import java.util.List; + import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Mojo; @@ -25,14 +27,30 @@ import com.diffplug.spotless.PaddedCell; import com.diffplug.spotless.maven.incremental.UpToDateChecker; +import org.apache.maven.plugins.annotations.Parameter; + /** * Performs formatting of all source files according to configured formatters. */ @Mojo(name = AbstractSpotlessMojo.GOAL_APPLY, threadSafe = true) public class SpotlessApplyMojo extends AbstractSpotlessMojo { + @Parameter(property = "spotlessIdeHook") + private String spotlessIdeHook; + + @Parameter(property = "spotlessIdeHookUseStdIn") + private boolean spotlessIdeHookUseStdIn; + + @Parameter(property = "spotlessIdeHookUseStdOut") + private boolean spotlessIdeHookUseStdOut; + @Override protected void process(Iterable files, Formatter formatter, UpToDateChecker upToDateChecker) throws MojoExecutionException { + if(isIdeHook()) { + IdeHook.performHook(files, spotlessIdeHook, formatter, getBaseDir(), null, spotlessIdeHookUseStdIn, spotlessIdeHookUseStdOut); + return; + } + ImpactedFilesTracker counter = new ImpactedFilesTracker(); for (File file : files) { @@ -69,4 +87,17 @@ protected void process(Iterable files, Formatter formatter, UpToDateChecke getLog().debug(String.format("Spotless.%s has no target files. Examine your ``: https://github.com/diffplug/spotless/tree/main/plugin-maven#quickstart", formatter.getName())); } } + + private boolean isIdeHook() { + return !(spotlessIdeHook == null || spotlessIdeHook.isEmpty()); + } + + private List fetchFileFromIdeHook() { + File file = new File(spotlessIdeHook); + if (!file.isAbsolute()) { + throw new PluginException("Argument passed to spotlessIdeHook must be an absolute path"); + } + + return List.of(file); + } } From ca026b868bce06f942f5f984aea279ae012437b2 Mon Sep 17 00:00:00 2001 From: Dimitrii Lipiridi Date: Thu, 24 Aug 2023 09:52:42 +0300 Subject: [PATCH 5/8] feat: Remove checking ratchetFrom from IDE hook --- .../gradle/spotless/FormatExtension.java | 2 +- .../spotless/maven/AbstractSpotlessMojo.java | 20 ++--- .../com/diffplug/spotless/maven/IdeHook.java | 76 +++++++++---------- .../spotless/maven/SpotlessApplyMojo.java | 18 +---- 4 files changed, 48 insertions(+), 68 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 0e4e4395c3..7a62f8cabf 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 @@ -124,7 +124,7 @@ public void setEncoding(String name) { /** @see #setRatchetFrom(String) */ public String getRatchetFrom() { - return ratchetFrom.equals(RATCHETFROM_NOT_SET_AT_FORMAT_LEVEL) ? spotless.getRatchetFrom() : ratchetFrom; + return ratchetFrom == RATCHETFROM_NOT_SET_AT_FORMAT_LEVEL ? spotless.getRatchetFrom() : ratchetFrom; } /** diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index 825859716f..2c295cef27 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -264,16 +264,16 @@ private List collectFiles(FormatterFactory formatterFactory, FormatterConf } final String[] includePatterns = this.filePatterns.split(","); final List compiledIncludePatterns = Arrays.stream(includePatterns) - .map(Pattern::compile) - .collect(Collectors.toList()); + .map(Pattern::compile) + .collect(Collectors.toList()); final Predicate shouldInclude = file -> compiledIncludePatterns - .stream() - .anyMatch(filePattern -> filePattern.matcher(file.getAbsolutePath()) - .matches()); + .stream() + .anyMatch(filePattern -> filePattern.matcher(file.getAbsolutePath()) + .matches()); return files - .stream() - .filter(shouldInclude) - .collect(toList()); + .stream() + .filter(shouldInclude) + .collect(toList()); } catch (IOException e) { throw new PluginException("Unable to scan file tree rooted at " + baseDir, e); } @@ -384,8 +384,4 @@ private UpToDateChecker createUpToDateChecker(Iterable formatters) { } return UpToDateChecker.wrapWithBuildContext(checker, buildContext); } - - protected File getBaseDir() { - return baseDir; - } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/IdeHook.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/IdeHook.java index dba9bcc547..0001046871 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/IdeHook.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/IdeHook.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 DiffPlug + * Copyright 2016-2023 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,64 +15,60 @@ */ package com.diffplug.spotless.maven; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + import com.diffplug.common.base.Errors; import com.diffplug.common.io.ByteStreams; import com.diffplug.spotless.Formatter; import com.diffplug.spotless.PaddedCell; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.List; - class IdeHook { private static void dumpIsClean() { System.err.println("IS CLEAN"); } - static void performHook(Iterable projectFiles, String path, Formatter formatter, File projectDir, String ratchetFrom, boolean spotlessIdeHookUseStdIn, boolean spotlessIdeHookUseStdOut) { + //No need to check ratchet (using isClean()) as it is performed in Gradle's IDE hook, since we have already gathered the available git files from ratchet. + static void performHook(Iterable projectFiles, Formatter formatter, String path, boolean spotlessIdeHookUseStdIn, boolean spotlessIdeHookUseStdOut) { File file = new File(path); if (!file.isAbsolute()) { System.err.println("Argument passed to spotlessIdeHook must be an absolute path"); return; } - if (projectContainsFile(projectFiles, file)) { - try { - if (ratchetFrom != null) { - GitRatchetMaven ratchet = GitRatchetMaven.instance(); - if (ratchet.isClean(projectDir, ratchet.rootTreeShaOf(projectDir, ratchetFrom), file)) { - dumpIsClean(); - return; - } - } - byte[] bytes; - if (spotlessIdeHookUseStdIn) { - bytes = ByteStreams.toByteArray(System.in); - } else { - bytes = Files.readAllBytes(file.toPath()); - } - PaddedCell.DirtyState dirty = PaddedCell.calculateDirtyState(formatter, file, bytes); - if (dirty.isClean()) { - dumpIsClean(); - } else if (dirty.didNotConverge()) { - System.err.println("DID NOT CONVERGE"); - System.err.println("Run 'spotlessDiagnose' for details https://github.com/diffplug/spotless/blob/main/PADDEDCELL.md"); + + if (!projectContainsFile(projectFiles, file)) { + return; + } + + try { + byte[] bytes; + if (spotlessIdeHookUseStdIn) { + bytes = ByteStreams.toByteArray(System.in); + } else { + bytes = Files.readAllBytes(file.toPath()); + } + PaddedCell.DirtyState dirty = PaddedCell.calculateDirtyState(formatter, file, bytes); + if (dirty.isClean()) { + dumpIsClean(); + } else if (dirty.didNotConverge()) { + System.err.println("DID NOT CONVERGE"); + System.err.println("See details https://github.com/diffplug/spotless/blob/main/PADDEDCELL.md"); + } else { + System.err.println("IS DIRTY"); + if (spotlessIdeHookUseStdOut) { + dirty.writeCanonicalTo(System.out); } else { - System.err.println("IS DIRTY"); - if (spotlessIdeHookUseStdOut) { - dirty.writeCanonicalTo(System.out); - } else { - dirty.writeCanonicalTo(file); - } + dirty.writeCanonicalTo(file); } - } catch (IOException e) { - e.printStackTrace(System.err); - throw Errors.asRuntime(e); - } finally { - System.err.close(); - System.out.close(); } + } catch (IOException e) { + e.printStackTrace(System.err); + throw Errors.asRuntime(e); + } finally { + System.err.close(); + System.out.close(); } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java index 9d5e3f9b14..07cc2cbc85 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java @@ -18,17 +18,14 @@ import java.io.File; import java.io.IOException; -import java.util.List; - import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; import com.diffplug.spotless.Formatter; import com.diffplug.spotless.PaddedCell; import com.diffplug.spotless.maven.incremental.UpToDateChecker; -import org.apache.maven.plugins.annotations.Parameter; - /** * Performs formatting of all source files according to configured formatters. */ @@ -46,8 +43,8 @@ public class SpotlessApplyMojo extends AbstractSpotlessMojo { @Override protected void process(Iterable files, Formatter formatter, UpToDateChecker upToDateChecker) throws MojoExecutionException { - if(isIdeHook()) { - IdeHook.performHook(files, spotlessIdeHook, formatter, getBaseDir(), null, spotlessIdeHookUseStdIn, spotlessIdeHookUseStdOut); + if (isIdeHook()) { + IdeHook.performHook(files, formatter, spotlessIdeHook, spotlessIdeHookUseStdIn, spotlessIdeHookUseStdOut); return; } @@ -91,13 +88,4 @@ protected void process(Iterable files, Formatter formatter, UpToDateChecke private boolean isIdeHook() { return !(spotlessIdeHook == null || spotlessIdeHook.isEmpty()); } - - private List fetchFileFromIdeHook() { - File file = new File(spotlessIdeHook); - if (!file.isAbsolute()) { - throw new PluginException("Argument passed to spotlessIdeHook must be an absolute path"); - } - - return List.of(file); - } } From 39c24abaa543e46f549409f16605052fca68a83f Mon Sep 17 00:00:00 2001 From: Dimitrii Lipiridi Date: Thu, 24 Aug 2023 09:52:51 +0300 Subject: [PATCH 6/8] feat: Add IDE hook tests --- .../diffplug/spotless/maven/IdeHookTest.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 plugin-maven/src/test/java/com/diffplug/spotless/maven/IdeHookTest.java diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/IdeHookTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/IdeHookTest.java new file mode 100644 index 0000000000..3c9a1a17d6 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/IdeHookTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2016-2023 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless.maven; + +import java.io.File; +import java.io.IOException; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.diffplug.spotless.ProcessRunner; + +class IdeHookTest extends MavenIntegrationHarness { + private String output, error; + private File dirty, clean, diverge, outofbounds; + + @BeforeEach + void before() throws IOException { + writePomWithFormatSteps("\n" + + " DIRTY.md\n" + + " CLEAN.md\n" + + " \n" + + " \n" + + " Greetings to Mars\n" + + " World\n" + + " Mars\n" + + " "); + + dirty = setFile("DIRTY.md").toContent("World"); + clean = setFile("CLEAN.md").toContent("Mars"); + outofbounds = setFile("OUTOFBOUNDS.md").toContent("Mars"); + ; + } + + private void runWith(String... arguments) throws IOException, InterruptedException { + ProcessRunner.Result result = mavenRunner() + .withArguments(arguments) + .runNoError(); + + this.output = result.stdOutUtf8(); + this.error = result.stdErrUtf8(); + } + + @Test + void dirty() throws IOException, InterruptedException { + runWith("spotless:apply", "--quiet", "-DspotlessIdeHook=\"" + dirty.getAbsolutePath() + "\"", "-DspotlessIdeHookUseStdOut=true"); + Assertions.assertThat(output).isEqualTo("Mars"); + Assertions.assertThat(error).startsWith("IS DIRTY"); + } + + @Test + void clean() throws IOException, InterruptedException { + runWith("spotless:apply", "--quiet", "-DspotlessIdeHook=" + clean.getAbsolutePath(), "-DspotlessIdeHookUseStdOut=true"); + Assertions.assertThat(output).isEmpty(); + Assertions.assertThat(error).startsWith("IS CLEAN"); + } + + @Test + void outofbounds() throws IOException, InterruptedException { + runWith("spotless:apply", "--quiet", "-DspotlessIdeHook=" + outofbounds.getAbsolutePath(), "-DspotlessIdeHookUseStdOut=true"); + Assertions.assertThat(output).isEmpty(); + Assertions.assertThat(error).isEmpty(); + } + + @Test + void notAbsolute() throws IOException, InterruptedException { + runWith("spotless:apply", "--quiet", "-DspotlessIdeHook=\"pom.xml\"", "-DspotlessIdeHookUseStdOut=true"); + Assertions.assertThat(output).isEmpty(); + Assertions.assertThat(error).contains("Argument passed to spotlessIdeHook must be an absolute path"); + } +} From c6e55bd4fe07fc1668c4d3727bbb83054c15ed08 Mon Sep 17 00:00:00 2001 From: Dimitrii Lipiridi Date: Thu, 24 Aug 2023 09:57:31 +0300 Subject: [PATCH 7/8] feat: Revert README.md --- plugin-maven/README.md | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/plugin-maven/README.md b/plugin-maven/README.md index 956dbf385e..cb770099ac 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -1601,22 +1601,13 @@ By default, `spotless:check` is bound to the `verify` phase. You might want to ## Can I apply Spotless to specific files? -There are two options: - -### Pattern You can target specific files by setting the `spotlessFiles` project property to a comma-separated list of file patterns: -``` -cmd> mvn spotless:apply -DspotlessFiles="src.main.java.com.example.*, .+Config.*\.java" -``` -The patterns are matched using `String#matches(String)` against the absolute file path. -### IDE Hook -You can specify a single file by providing the `spotlessIdeHook` argument, which accepts the absolute path of the file. ``` -cmd> mvn spotless:apply -DspotlessIdeHook="C:\my-project\src\main\java\com\example\Application.java" - +cmd> mvn spotless:apply -DspotlessFiles=my/file/pattern.java,more/generic/.*-pattern.java ``` -This option ignores the ratchetFrom property. + +The patterns are matched using `String#matches(String)` against the absolute file path. From 5ddf6e075323c53934a4f8c3ca98a346ec144f3c Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Thu, 28 Sep 2023 14:34:56 -0700 Subject: [PATCH 8/8] Update changelog. --- plugin-maven/CHANGES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index ed6ce8fe49..1338d42ddb 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] ### Added +* Add `-DspotlessIdeHook` that provides the ability to apply Spotless exclusively to a specified file. It accepts the absolute path of the file. ([#1782](https://github.com/diffplug/spotless/pull/1782)) + * BETA, subject to change until we have proven compatibility with some IDE plugins. * Added support for `google-java-format`'s `skip-javadoc-formatting` option ([#1793](https://github.com/diffplug/spotless/pull/1793)) * Added support for biome. The Rome project [was renamed to Biome](https://biomejs.dev/blog/annoucing-biome/). The configuration is still the same, but you should switch to the new `` tag and adjust @@ -31,7 +33,6 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( ### Added * Add a `jsonPatch` step to `json` formatter configurations. This allows patching of JSON documents using [JSON Patches](https://jsonpatch.com). ([#1753](https://github.com/diffplug/spotless/pull/1753)) * Support GJF own import order. ([#1780](https://github.com/diffplug/spotless/pull/1780)) -* Add `-DspotlessIdeHook` that provides the ability to apply Spotless exclusively to a specified file. It accepts the absolute path of the file. ([#200](https://github.com/diffplug/spotless/issues/200)) ### Fixed * Add support for `prettier` version `3.0.0` and newer. ([#1760](https://github.com/diffplug/spotless/pull/1760), [#1751](https://github.com/diffplug/spotless/issues/1751)) * Fix npm install calls when npm cache is not up-to-date. ([#1760](https://github.com/diffplug/spotless/pull/1760), [#1750](https://github.com/diffplug/spotless/issues/1750))