Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
## [Unreleased]
### Changes
* We are now opting in to Gradle's new stable configuration cache. ([#1591](https://github.com/diffplug/spotless/pull/1591))
* Support a file name field in license headers. ([#1605](https://github.com/diffplug/spotless/pull/1605))

## [2.36.0] - 2023-02-27
### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public FormatterStep build() {
throw new IllegalStateException(yearMode.toString());
}
return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesMatching);
}, step -> step::format);
}, step -> FormatterFunc.needsFile(step::format));
}

if (contentPattern == null) {
Expand Down Expand Up @@ -214,6 +214,8 @@ private static class Runtime implements Serializable {
private final boolean updateYearWithLatest;
private final boolean licenseHeaderWithRange;

private static final Pattern FILENAME_PATTERN = Pattern.compile("\\$FILE");

/** The license that we'd like enforced. */
private Runtime(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest, @Nullable String skipLinesMatching) {
if (delimiter.contains("\n")) {
Expand Down Expand Up @@ -266,9 +268,9 @@ private static Optional<String> getYearToken(String licenseHeader) {
}

/** Formats the given string. */
private String format(String raw) {
private String format(String raw, File file) {
if (skipLinesMatching == null) {
return addOrUpdateLicenseHeader(raw);
return addOrUpdateLicenseHeader(raw, file);
} else {
String[] lines = raw.split("\n");
StringBuilder skippedLinesBuilder = new StringBuilder();
Expand All @@ -287,11 +289,11 @@ private String format(String raw) {
remainingLinesBuilder.append(line).append('\n');
}
}
return skippedLinesBuilder + addOrUpdateLicenseHeader(remainingLinesBuilder.toString());
return skippedLinesBuilder + addOrUpdateLicenseHeader(remainingLinesBuilder.toString(), file);
}
}

private String addOrUpdateLicenseHeader(String raw) {
private String addOrUpdateLicenseHeader(String raw, File file) {
Matcher contentMatcher = delimiterPattern.matcher(raw);
if (!contentMatcher.find()) {
throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern);
Expand All @@ -305,13 +307,14 @@ private String addOrUpdateLicenseHeader(String raw) {
return raw;
} else {
// otherwise we'll have to add the header
return yearSepOrFull + content;
return replaceFileName(yearSepOrFull, file) + content;
}
} else {
// the yes year case is a bit harder
int beforeYearIdx = raw.indexOf(beforeYear);
int afterYearIdx = raw.indexOf(afterYear, beforeYearIdx + beforeYear.length() + 1);

String header;
if (beforeYearIdx >= 0 && afterYearIdx >= 0 && afterYearIdx + afterYear.length() <= contentMatcher.start()) {
// and also ends with exactly the right header, so it's easy to parse the existing year
String existingYear = raw.substring(beforeYearIdx + beforeYear.length(), afterYearIdx);
Expand All @@ -323,12 +326,13 @@ private String addOrUpdateLicenseHeader(String raw) {
return raw;
}
}
return beforeYear + newYear + afterYear + content;
header = beforeYear + newYear + afterYear;
} else {
String newYear = calculateYearBySearching(raw.substring(0, contentMatcher.start()));
// at worst, we just say that it was made today
return beforeYear + newYear + afterYear + content;
header = beforeYear + newYear + afterYear;
}
return replaceFileName(header, file) + content;
}
}
}
Expand Down Expand Up @@ -421,6 +425,10 @@ private String setLicenseHeaderYearsFromGitHistory(String raw, File file) throws
return beforeYear + yearRange + afterYear + raw.substring(contentMatcher.start());
}

private String replaceFileName(String header, File file) {
return FILENAME_PATTERN.matcher(header).replaceAll(file.getName());
}

private static String parseYear(String cmd, File file) throws IOException {
String fullCmd = cmd + " -- " + file.getAbsolutePath();
ProcessBuilder builder = new ProcessBuilder().directory(file.getParentFile());
Expand Down
14 changes: 11 additions & 3 deletions testlib/src/main/java/com/diffplug/spotless/StepHarness.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,22 @@ public static StepHarness forFormatter(Formatter formatter) {

/** Asserts that the given element is transformed as expected, and that the result is idempotent. */
public StepHarness test(String before, String after) {
String actual = formatter.compute(LineEnding.toUnix(before), new File(""));
return test(before, after, "");
}

public StepHarness test(String before, String after, String fileName) {
String actual = formatter.compute(LineEnding.toUnix(before), new File(fileName));
assertEquals(after, actual, "Step application failed");
return testUnaffected(after);
return testUnaffected(after, fileName);
}

/** Asserts that the given element is idempotent w.r.t the step under test. */
public StepHarness testUnaffected(String idempotentElement) {
String actual = formatter.compute(LineEnding.toUnix(idempotentElement), new File(""));
return testUnaffected(idempotentElement, "");
}

public StepHarness testUnaffected(String idempotentElement, String fileName) {
String actual = formatter.compute(LineEnding.toUnix(idempotentElement), new File(fileName));
assertEquals(idempotentElement, actual, "Step is not idempotent");
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class LicenseHeaderStepTest extends ResourceHarness {
private static final String package_ = "package ";
private static final String HEADER_WITH_$YEAR = "This is a fake license, $YEAR. ACME corp.";
private static final String HEADER_WITH_RANGE_TO_$YEAR = "This is a fake license with range, 2009-$YEAR. ACME corp.";
private static final String HEADER_WITH_$FILE = "This is a fake license, $FILE. ACME corp.";
private static final String HEADER_WITH_$YEAR_$FILE = "This is a fake license, $FILE, $YEAR. ACME corp.";

@Test
void parseExistingYear() throws Exception {
Expand Down Expand Up @@ -163,6 +165,16 @@ private String hasHeaderWithRangeAndWithYearTo(String toYear) throws IOException
return hasHeaderYear(HEADER_WITH_RANGE_TO_$YEAR, toYear);
}

private String hasHeaderFileName(String license, String fileName) throws IOException {
return header(license).replace("$FILE", fileName) + getTestResource(FILE_NO_LICENSE);
}

private String hasHeaderYearFileName(String license, String year, String fileName) throws IOException {
return header(license)
.replace("$YEAR", year)
.replace("$FILE", fileName) + getTestResource(FILE_NO_LICENSE);
}

private static String currentYear() {
return String.valueOf(YearMonth.now().getYear());
}
Expand Down Expand Up @@ -250,4 +262,22 @@ void should_preserve_year_for_license_with_address() throws Throwable {
hasHeader(licenceWithAddress().replace("$YEAR", "2015").replace("FooBar Inc. All", "FooBar Inc. All")),
hasHeader(licenceWithAddress().replace("$YEAR", "2015")));
}

@Test
void should_apply_license_containing_filename_token() throws Exception {
FormatterStep step = LicenseHeaderStep.headerDelimiter(header(HEADER_WITH_$FILE), package_).build();
StepHarness.forStep(step)
.test(getTestResource(FILE_NO_LICENSE), hasHeaderFileName(HEADER_WITH_$FILE, "Test.java"), "Test.java");
}

@Test
void should_apply_license_containing_YEAR_filename_token() throws Exception {
FormatterStep step = LicenseHeaderStep.headerDelimiter(header(HEADER_WITH_$YEAR_$FILE), package_).build();
StepHarness.forStep(step)
.test(
getTestResource(FILE_NO_LICENSE),
hasHeaderYearFileName(HEADER_WITH_$YEAR_$FILE, currentYear(), "Test.java"),
"Test.java"
);
}
}