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+
}

0 commit comments

Comments
 (0)