Skip to content

Commit cdcfe14

Browse files
committed
Merge branch 'main' into feat/equo-solstice
2 parents f93fccc + f2558fe commit cdcfe14

35 files changed

+344
-106
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ jobs:
3333
with:
3434
gradle-home-cache-cleanup: true
3535
- name: spotlessCheck
36-
run: ./gradlew spotlessCheck --build-cache
36+
run: ./gradlew spotlessCheck
3737
- name: assemble testClasses
38-
run: ./gradlew assemble testClasses --build-cache
38+
run: ./gradlew assemble testClasses
3939
build:
4040
needs: sanityCheck
4141
strategy:
@@ -71,13 +71,13 @@ jobs:
7171
gradle-home-cache-cleanup: true
7272
- name: build (maven-only)
7373
if: matrix.kind == 'maven'
74-
run: ./gradlew :plugin-maven:build -x spotlessCheck --build-cache
74+
run: ./gradlew :plugin-maven:build -x spotlessCheck
7575
- name: build (everything-but-maven)
7676
if: matrix.kind == 'gradle'
77-
run: ./gradlew build -x spotlessCheck --build-cache -PSPOTLESS_EXCLUDE_MAVEN=true
77+
run: ./gradlew build -x spotlessCheck -PSPOTLESS_EXCLUDE_MAVEN=true
7878
- name: test npm
7979
if: matrix.kind == 'npm'
80-
run: ./gradlew testNpm --build-cache
80+
run: ./gradlew testNpm
8181
- name: junit result
8282
uses: mikepenz/action-junit-report@v3
8383
if: always() # always run even if the previous step fails

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ This document is intended for Spotless developers.
1010
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
1111

1212
## [Unreleased]
13+
### Added
14+
* You can now put the filename into a license header template with `$FILE`. ([#1605](https://github.com/diffplug/spotless/pull/1605) fixes [#1147](https://github.com/diffplug/spotless/issues/1147))
1315
### Changes
1416
* We are now opting in to Gradle's new stable configuration cache. ([#1591](https://github.com/diffplug/spotless/pull/1591))
1517
* Adopt [Equo Solstice OSGi and p2 shim](https://github.com/equodev/equo-ide/tree/main/solstice) to update all Eclipse-based plugins. ([#1524](https://github.com/diffplug/spotless/pull/1524))

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ VER_SLF4J=[1.6,2.0[
2929

3030
# Used in multiple places
3131
VER_DURIAN=1.2.0
32-
VER_JGIT=6.4.0.202211300538-r
32+
VER_JGIT=6.5.0.202303070854-r
3333
VER_JUNIT=5.9.2
3434
VER_ASSERTJ=3.24.2
35-
VER_MOCKITO=5.1.1
35+
VER_MOCKITO=5.2.0

lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545

4646
/** Prefixes a license header before the package statement. */
4747
public final class LicenseHeaderStep {
48+
public static final String DEFAULT_JAVA_HEADER_DELIMITER = "(package|import|public|class|module) ";
4849
private static final Logger LOGGER = LoggerFactory.getLogger(LicenseHeaderStep.class);
4950

5051
public enum YearMode {
@@ -142,7 +143,7 @@ public FormatterStep build() {
142143
throw new IllegalStateException(yearMode.toString());
143144
}
144145
return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesMatching);
145-
}, step -> step::format);
146+
}, step -> FormatterFunc.needsFile(step::format));
146147
}
147148

148149
if (contentPattern == null) {
@@ -213,6 +214,9 @@ private static class Runtime implements Serializable {
213214
private final @Nullable String afterYear;
214215
private final boolean updateYearWithLatest;
215216
private final boolean licenseHeaderWithRange;
217+
private final boolean hasFileToken;
218+
219+
private static final Pattern FILENAME_PATTERN = Pattern.compile("\\$FILE");
216220

217221
/** The license that we'd like enforced. */
218222
private Runtime(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest, @Nullable String skipLinesMatching) {
@@ -226,6 +230,7 @@ private Runtime(String licenseHeader, String delimiter, String yearSeparator, bo
226230
}
227231
this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE);
228232
this.skipLinesMatching = skipLinesMatching == null ? null : Pattern.compile(skipLinesMatching);
233+
this.hasFileToken = FILENAME_PATTERN.matcher(licenseHeader).find();
229234

230235
Optional<String> yearToken = getYearToken(licenseHeader);
231236
if (yearToken.isPresent()) {
@@ -266,9 +271,9 @@ private static Optional<String> getYearToken(String licenseHeader) {
266271
}
267272

268273
/** Formats the given string. */
269-
private String format(String raw) {
274+
private String format(String raw, File file) {
270275
if (skipLinesMatching == null) {
271-
return addOrUpdateLicenseHeader(raw);
276+
return addOrUpdateLicenseHeader(raw, file);
272277
} else {
273278
String[] lines = raw.split("\n");
274279
StringBuilder skippedLinesBuilder = new StringBuilder();
@@ -287,11 +292,17 @@ private String format(String raw) {
287292
remainingLinesBuilder.append(line).append('\n');
288293
}
289294
}
290-
return skippedLinesBuilder + addOrUpdateLicenseHeader(remainingLinesBuilder.toString());
295+
return skippedLinesBuilder + addOrUpdateLicenseHeader(remainingLinesBuilder.toString(), file);
291296
}
292297
}
293298

294-
private String addOrUpdateLicenseHeader(String raw) {
299+
private String addOrUpdateLicenseHeader(String raw, File file) {
300+
raw = replaceYear(raw);
301+
raw = replaceFileName(raw, file);
302+
return raw;
303+
}
304+
305+
private String replaceYear(String raw) {
295306
Matcher contentMatcher = delimiterPattern.matcher(raw);
296307
if (!contentMatcher.find()) {
297308
throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern);
@@ -421,6 +432,19 @@ private String setLicenseHeaderYearsFromGitHistory(String raw, File file) throws
421432
return beforeYear + yearRange + afterYear + raw.substring(contentMatcher.start());
422433
}
423434

435+
private String replaceFileName(String raw, File file) {
436+
if (!hasFileToken) {
437+
return raw;
438+
}
439+
Matcher contentMatcher = delimiterPattern.matcher(raw);
440+
if (!contentMatcher.find()) {
441+
throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern);
442+
}
443+
String header = raw.substring(0, contentMatcher.start());
444+
String content = raw.substring(contentMatcher.start());
445+
return FILENAME_PATTERN.matcher(header).replaceAll(file.getName()) + content;
446+
}
447+
424448
private static String parseYear(String cmd, File file) throws IOException {
425449
String fullCmd = cmd + " -- " + file.getAbsolutePath();
426450
ProcessBuilder builder = new ProcessBuilder().directory(file.getParentFile());

plugin-gradle/CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).
44

55
## [Unreleased]
6+
### Added
7+
* You can now put the filename into a license header template with `$FILE`. ([#1605](https://github.com/diffplug/spotless/pull/1605) fixes [#1147](https://github.com/diffplug/spotless/issues/1147))
8+
* `licenseHeader` default pattern for Java files is updated to `(package|import|public|class|module) `. ([#1614](https://github.com/diffplug/spotless/pull/1614))
69

710
## [6.16.0] - 2023-02-27
811
### Added

plugin-gradle/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,8 +430,8 @@ spotless {
430430
```gradle
431431
spotless {
432432
scala {
433-
// version and configFile, majorScalaVersion are all optional
434-
scalafmt('3.5.9').configFile('scalafmt.conf').majorScalaVersion('2.13')
433+
// version and configFile, scalaMajorVersion are all optional
434+
scalafmt('3.5.9').configFile('scalafmt.conf').scalaMajorVersion('2.13')
435435
```
436436
437437
<a name="applying-to-cc-sources"></a>

plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,7 @@ public JavaExtension(SpotlessExtension spotless) {
5050
super(spotless);
5151
}
5252

53-
// If this constant changes, don't forget to change the similarly-named one in
54-
// testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java as well
55-
static final String LICENSE_HEADER_DELIMITER = "package ";
53+
static final String LICENSE_HEADER_DELIMITER = LicenseHeaderStep.DEFAULT_JAVA_HEADER_DELIMITER;
5654

5755
@Override
5856
public LicenseHeaderConfig licenseHeader(String licenseHeader) {

plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessTaskImpl.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2022 DiffPlug
2+
* Copyright 2016-2023 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
3535
import org.gradle.work.FileChange;
3636
import org.gradle.work.InputChanges;
3737

38+
import com.diffplug.common.annotations.VisibleForTesting;
3839
import com.diffplug.common.base.StringPrinter;
3940
import com.diffplug.spotless.Formatter;
4041
import com.diffplug.spotless.PaddedCell;
@@ -92,28 +93,37 @@ public void performAction(InputChanges inputs) throws Exception {
9293
}
9394
}
9495

95-
private void processInputFile(@Nullable GitRatchet ratchet, Formatter formatter, File input) throws IOException {
96+
@VisibleForTesting
97+
void processInputFile(@Nullable GitRatchet ratchet, Formatter formatter, File input) throws IOException {
9698
File output = getOutputFile(input);
97-
getLogger().debug("Applying format to " + input + " and writing to " + output);
99+
getLogger().debug("Applying format to {} and writing to {}", input, output);
98100
PaddedCell.DirtyState dirtyState;
99101
if (ratchet != null && ratchet.isClean(getProjectDir().get().getAsFile(), getRootTreeSha(), input)) {
100102
dirtyState = PaddedCell.isClean();
101103
} else {
102-
dirtyState = PaddedCell.calculateDirtyState(formatter, input);
104+
try {
105+
dirtyState = PaddedCell.calculateDirtyState(formatter, input);
106+
} catch (IOException e) {
107+
throw new IOException("Issue processing file: " + input, e);
108+
} catch (RuntimeException e) {
109+
throw new IllegalArgumentException("Issue processing file: " + input, e);
110+
}
103111
}
104112
if (dirtyState.isClean()) {
105113
// Remove previous output if it exists
106114
Files.deleteIfExists(output.toPath());
107115
} else if (dirtyState.didNotConverge()) {
108-
getLogger().warn("Skipping '" + input + "' because it does not converge. Run {@code spotlessDiagnose} to understand why");
116+
getLogger().warn("Skipping '{}' because it does not converge. Run {@code spotlessDiagnose} to understand why", input);
109117
} else {
110118
Path parentDir = output.toPath().getParent();
111119
if (parentDir == null) {
112-
throw new IllegalStateException("Every file has a parent folder.");
120+
throw new IllegalStateException("Every file has a parent folder. But not: " + output);
113121
}
114122
Files.createDirectories(parentDir);
115123
// Need to copy the original file to the tmp location just to remember the file attributes
116124
Files.copy(input.toPath(), output.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
125+
126+
getLogger().info(String.format("Writing clean file: %s", output));
117127
dirtyState.writeCanonicalTo(output);
118128
}
119129
}

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/CleanthatJavaIntegrationTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ void integration() throws IOException {
3737
" }",
3838
"}");
3939

40-
setFile("test.java").toResource("java/cleanthat/MultipleMutators.dirty.java");
40+
setFile("test.java").toResource("java/cleanthat/MultipleMutators.dirty.test");
4141
gradleRunner().withArguments("spotlessApply").build();
42-
assertFile("test.java").sameAsResource("java/cleanthat/MultipleMutators.clean.java");
42+
assertFile("test.java").sameAsResource("java/cleanthat/MultipleMutators.clean.test");
4343
}
4444
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2023 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.gradle.spotless;
17+
18+
import java.io.File;
19+
import java.nio.file.Paths;
20+
21+
import org.assertj.core.api.Assertions;
22+
import org.gradle.api.file.DirectoryProperty;
23+
import org.gradle.api.logging.Logger;
24+
import org.junit.jupiter.api.Test;
25+
import org.mockito.Mockito;
26+
27+
import com.diffplug.spotless.Formatter;
28+
29+
public class SpotlessTaskImplTest {
30+
@Test
31+
public void testThrowsMessageContainsFilename() throws Exception {
32+
SpotlessTaskImpl task = Mockito.mock(SpotlessTaskImpl.class, Mockito.CALLS_REAL_METHODS);
33+
Mockito.when(task.getLogger()).thenReturn(Mockito.mock(Logger.class));
34+
35+
File projectDir = Paths.get("unitTests", "projectDir").toFile();
36+
DirectoryProperty projectDirProperty = Mockito.mock(DirectoryProperty.class, Mockito.RETURNS_DEEP_STUBS);
37+
Mockito.when(projectDirProperty.get().getAsFile()).thenReturn(projectDir);
38+
39+
Mockito.when(task.getProjectDir()).thenReturn(projectDirProperty);
40+
41+
File input = Paths.get("unitTests", "projectDir", "someInput").toFile();
42+
Formatter formatter = Mockito.mock(Formatter.class);
43+
44+
Assertions.assertThatThrownBy(() -> task.processInputFile(null, formatter, input)).hasMessageContaining(input.toString());
45+
}
46+
}

plugin-maven/CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
44

55
## [Unreleased]
6+
### Added
7+
* You can now put the filename into a license header template with `$FILE`. ([#1605](https://github.com/diffplug/spotless/pull/1605) fixes [#1147](https://github.com/diffplug/spotless/issues/1147))
8+
### Fixed
9+
* `licenseHeader` default pattern for Java files is updated to `(package|import|public|class|module) `. ([#1614](https://github.com/diffplug/spotless/pull/1614))
10+
### Changes
11+
* Enable incremental up-to-date checking by default. ([#1621](https://github.com/diffplug/spotless/pull/1621))
612

713
## [2.34.0] - 2023-02-27
814
### Added

plugin-maven/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1262,7 +1262,7 @@ To define what lines to skip at the beginning of such files, fill the `skipLines
12621262

12631263
## Incremental up-to-date checking and formatting
12641264

1265-
**This feature is turned off by default.**
1265+
**This feature is enabled by default starting from version 2.35.0.**
12661266

12671267
Execution of `spotless:check` and `spotless:apply` for large projects can take time.
12681268
By default, Spotless Maven plugin needs to read and format each source file.

plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo {
187187
private String setLicenseHeaderYearsFromGitHistory;
188188

189189
@Parameter
190-
private UpToDateChecking upToDateChecking;
190+
private UpToDateChecking upToDateChecking = UpToDateChecking.enabled();
191191

192192
protected abstract void process(Iterable<File> files, Formatter formatter, UpToDateChecker upToDateChecker) throws MojoExecutionException;
193193

@@ -373,9 +373,9 @@ private UpToDateChecker createUpToDateChecker(Iterable<Formatter> formatters) {
373373
}
374374
final UpToDateChecker checker;
375375
if (upToDateChecking != null && upToDateChecking.isEnabled()) {
376-
getLog().info("Up-to-date checking enabled");
377376
checker = UpToDateChecker.forProject(project, indexFile, formatters, getLog());
378377
} else {
378+
getLog().info("Up-to-date checking disabled");
379379
checker = UpToDateChecker.noop(project, indexFile, getLog());
380380
}
381381
return UpToDateChecker.wrapWithBuildContext(checker, buildContext);

plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessApplyMojo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ protected void process(Iterable<File> files, Formatter formatter, UpToDateChecke
5454
} else {
5555
counter.checkedButAlreadyClean();
5656
}
57-
} catch (IOException e) {
57+
} catch (IOException | RuntimeException e) {
5858
throw new MojoExecutionException("Unable to format file " + file, e);
5959
}
6060

plugin-maven/src/main/java/com/diffplug/spotless/maven/SpotlessCheckMojo.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2021 DiffPlug
2+
* Copyright 2016-2023 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -38,9 +38,12 @@ public class SpotlessCheckMojo extends AbstractSpotlessMojo {
3838

3939
@Override
4040
protected void process(Iterable<File> files, Formatter formatter, UpToDateChecker upToDateChecker) throws MojoExecutionException {
41+
ImpactedFilesTracker counter = new ImpactedFilesTracker();
42+
4143
List<File> problemFiles = new ArrayList<>();
4244
for (File file : files) {
4345
if (upToDateChecker.isUpToDate(file.toPath())) {
46+
counter.skippedAsCleanCache();
4447
if (getLog().isDebugEnabled()) {
4548
getLog().debug("Spotless will not check an up-to-date file: " + file);
4649
}
@@ -51,14 +54,24 @@ protected void process(Iterable<File> files, Formatter formatter, UpToDateChecke
5154
PaddedCell.DirtyState dirtyState = PaddedCell.calculateDirtyState(formatter, file);
5255
if (!dirtyState.isClean() && !dirtyState.didNotConverge()) {
5356
problemFiles.add(file);
57+
counter.cleaned();
5458
} else {
59+
counter.checkedButAlreadyClean();
5560
upToDateChecker.setUpToDate(file.toPath());
5661
}
57-
} catch (IOException e) {
62+
} catch (IOException | RuntimeException e) {
5863
throw new MojoExecutionException("Unable to format file " + file, e);
5964
}
6065
}
6166

67+
// We print the number of considered files which is useful when ratchetFrom is setup
68+
if (counter.getTotal() > 0) {
69+
getLog().info(String.format("Spotless.%s is keeping %s files clean - %s needs changes to be clean, %s were already clean, %s were skipped because caching determined they were already clean",
70+
formatter.getName(), counter.getTotal(), counter.getCleaned(), counter.getCheckedButAlreadyClean(), counter.getSkippedAsCleanCache()));
71+
} else {
72+
getLog().debug(String.format("Spotless.%s has no target files. Examine your `<includes>`: https://github.com/diffplug/spotless/tree/main/plugin-maven#quickstart", formatter.getName()));
73+
}
74+
6275
if (!problemFiles.isEmpty()) {
6376
throw new MojoExecutionException(DiffMessageFormatter.builder()
6477
.runToFix("Run 'mvn spotless:apply' to fix these violations.")

plugin-maven/src/main/java/com/diffplug/spotless/maven/groovy/Groovy.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.apache.maven.project.MavenProject;
2121

2222
import com.diffplug.common.collect.ImmutableSet;
23+
import com.diffplug.spotless.generic.LicenseHeaderStep;
2324
import com.diffplug.spotless.maven.FormatterFactory;
2425
import com.diffplug.spotless.maven.generic.LicenseHeader;
2526

@@ -32,7 +33,7 @@
3233
public class Groovy extends FormatterFactory {
3334

3435
private static final Set<String> DEFAULT_INCLUDES = ImmutableSet.of("src/main/groovy/**/*.groovy", "src/test/groovy/**/*.groovy");
35-
private static final String LICENSE_HEADER_DELIMITER = "package ";
36+
private static final String LICENSE_HEADER_DELIMITER = LicenseHeaderStep.DEFAULT_JAVA_HEADER_DELIMITER;
3637

3738
@Override
3839
public Set<String> defaultIncludes(MavenProject project) {

0 commit comments

Comments
 (0)