Skip to content

Commit 7477651

Browse files
authored
Support $FILE in license headers (#1605)
2 parents ec85679 + 40488be commit 7477651

File tree

5 files changed

+77
-5
lines changed

5 files changed

+77
-5
lines changed

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

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

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ public FormatterStep build() {
143143
throw new IllegalStateException(yearMode.toString());
144144
}
145145
return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesMatching);
146-
}, step -> step::format);
146+
}, step -> FormatterFunc.needsFile(step::format));
147147
}
148148

149149
if (contentPattern == null) {
@@ -214,6 +214,9 @@ private static class Runtime implements Serializable {
214214
private final @Nullable String afterYear;
215215
private final boolean updateYearWithLatest;
216216
private final boolean licenseHeaderWithRange;
217+
private final boolean hasFileToken;
218+
219+
private static final Pattern FILENAME_PATTERN = Pattern.compile("\\$FILE");
217220

218221
/** The license that we'd like enforced. */
219222
private Runtime(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest, @Nullable String skipLinesMatching) {
@@ -227,6 +230,7 @@ private Runtime(String licenseHeader, String delimiter, String yearSeparator, bo
227230
}
228231
this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE);
229232
this.skipLinesMatching = skipLinesMatching == null ? null : Pattern.compile(skipLinesMatching);
233+
this.hasFileToken = FILENAME_PATTERN.matcher(licenseHeader).find();
230234

231235
Optional<String> yearToken = getYearToken(licenseHeader);
232236
if (yearToken.isPresent()) {
@@ -267,9 +271,9 @@ private static Optional<String> getYearToken(String licenseHeader) {
267271
}
268272

269273
/** Formats the given string. */
270-
private String format(String raw) {
274+
private String format(String raw, File file) {
271275
if (skipLinesMatching == null) {
272-
return addOrUpdateLicenseHeader(raw);
276+
return addOrUpdateLicenseHeader(raw, file);
273277
} else {
274278
String[] lines = raw.split("\n");
275279
StringBuilder skippedLinesBuilder = new StringBuilder();
@@ -288,11 +292,17 @@ private String format(String raw) {
288292
remainingLinesBuilder.append(line).append('\n');
289293
}
290294
}
291-
return skippedLinesBuilder + addOrUpdateLicenseHeader(remainingLinesBuilder.toString());
295+
return skippedLinesBuilder + addOrUpdateLicenseHeader(remainingLinesBuilder.toString(), file);
292296
}
293297
}
294298

295-
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) {
296306
Matcher contentMatcher = delimiterPattern.matcher(raw);
297307
if (!contentMatcher.find()) {
298308
throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern);
@@ -422,6 +432,19 @@ private String setLicenseHeaderYearsFromGitHistory(String raw, File file) throws
422432
return beforeYear + yearRange + afterYear + raw.substring(contentMatcher.start());
423433
}
424434

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+
425448
private static String parseYear(String cmd, File file) throws IOException {
426449
String fullCmd = cmd + " -- " + file.getAbsolutePath();
427450
ProcessBuilder builder = new ProcessBuilder().directory(file.getParentFile());

plugin-gradle/CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
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))
68
* `licenseHeader` default pattern for Java files is updated to `(package|import|public|class|module) `. ([#1614](https://github.com/diffplug/spotless/pull/1614))
79

810
## [6.16.0] - 2023-02-27

plugin-maven/CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
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))
68
### Fixed
79
* `licenseHeader` default pattern for Java files is updated to `(package|import|public|class|module) `. ([#1614](https://github.com/diffplug/spotless/pull/1614))
810

testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@
2828
import com.diffplug.spotless.ResourceHarness;
2929
import com.diffplug.spotless.SerializableEqualityTester;
3030
import com.diffplug.spotless.StepHarness;
31+
import com.diffplug.spotless.StepHarnessWithFile;
3132
import com.diffplug.spotless.generic.LicenseHeaderStep.YearMode;
3233

3334
class LicenseHeaderStepTest extends ResourceHarness {
3435
private static final String FILE_NO_LICENSE = "license/FileWithoutLicenseHeader.test";
3536
private static final String package_ = LicenseHeaderStep.DEFAULT_JAVA_HEADER_DELIMITER;
3637
private static final String HEADER_WITH_$YEAR = "This is a fake license, $YEAR. ACME corp.";
3738
private static final String HEADER_WITH_RANGE_TO_$YEAR = "This is a fake license with range, 2009-$YEAR. ACME corp.";
39+
private static final String HEADER_WITH_$FILE = "This is a fake license, $FILE. ACME corp.";
40+
private static final String HEADER_WITH_$YEAR_$FILE = "This is a fake license, $FILE, $YEAR. ACME corp.";
3841

3942
@Test
4043
void parseExistingYear() throws Exception {
@@ -163,6 +166,16 @@ private String hasHeaderWithRangeAndWithYearTo(String toYear) throws IOException
163166
return hasHeaderYear(HEADER_WITH_RANGE_TO_$YEAR, toYear);
164167
}
165168

169+
private String hasHeaderFileName(String license, String fileName) throws IOException {
170+
return header(license).replace("$FILE", fileName) + getTestResource(FILE_NO_LICENSE);
171+
}
172+
173+
private String hasHeaderYearFileName(String license, String year, String fileName) throws IOException {
174+
return header(license)
175+
.replace("$YEAR", year)
176+
.replace("$FILE", fileName) + getTestResource(FILE_NO_LICENSE);
177+
}
178+
166179
private static String currentYear() {
167180
return String.valueOf(YearMonth.now().getYear());
168181
}
@@ -252,6 +265,36 @@ void should_preserve_year_for_license_with_address() throws Throwable {
252265
}
253266

254267
@Test
268+
void should_apply_license_containing_filename_token() throws Exception {
269+
FormatterStep step = LicenseHeaderStep.headerDelimiter(header(HEADER_WITH_$FILE), package_).build();
270+
StepHarnessWithFile.forStep(this, step)
271+
.test(new File("Test.java"), getTestResource(FILE_NO_LICENSE), hasHeaderFileName(HEADER_WITH_$FILE, "Test.java"))
272+
.testUnaffected(new File("Test.java"), hasHeaderFileName(HEADER_WITH_$FILE, "Test.java"));
273+
}
274+
275+
@Test
276+
void should_update_license_containing_filename_token() throws Exception {
277+
FormatterStep step = LicenseHeaderStep.headerDelimiter(header(HEADER_WITH_$FILE), package_).build();
278+
StepHarnessWithFile.forStep(this, step)
279+
.test(
280+
new File("After.java"),
281+
hasHeaderFileName(HEADER_WITH_$FILE, "Before.java"),
282+
hasHeaderFileName(HEADER_WITH_$FILE, "After.java"));
283+
}
284+
285+
@Test
286+
void should_apply_license_containing_YEAR_filename_token() throws Exception {
287+
FormatterStep step = LicenseHeaderStep.headerDelimiter(header(HEADER_WITH_$YEAR_$FILE), package_).build();
288+
StepHarnessWithFile.forStep(this, step)
289+
.test(
290+
new File("Test.java"),
291+
getTestResource(FILE_NO_LICENSE),
292+
hasHeaderYearFileName(HEADER_WITH_$YEAR_$FILE, currentYear(), "Test.java"))
293+
.testUnaffected(
294+
new File("Test.java"),
295+
hasHeaderYearFileName(HEADER_WITH_$YEAR_$FILE, currentYear(), "Test.java"));
296+
}
297+
255298
void noPackage() throws Throwable {
256299
String header = header(getTestResource("license/TestLicense"));
257300
FormatterStep step = LicenseHeaderStep.headerDelimiter(header, package_).build();

0 commit comments

Comments
 (0)