Skip to content

Enable support for intelliJ placeholder for year in license header #542

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 20, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This document is intended for Spotless developers.
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
### Added
* Enable IntelliJ-compatible token `$today.year` for specifying the year in license header files. ([#542](https://github.com/diffplug/spotless/pull/542))
### Build
* All `CHANGES.md` are now in keepachangelog format. ([#507](https://github.com/diffplug/spotless/pull/507))
* We now use [javadoc.io](https://javadoc.io/) instead of github pages. ([#508](https://github.com/diffplug/spotless/pull/508))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.time.YearMonth;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -35,17 +38,18 @@ public final class LicenseHeaderStep implements Serializable {

private static final String NAME = "licenseHeader";
private static final String DEFAULT_YEAR_DELIMITER = "-";
private static final List<String> YEAR_TOKENS = Arrays.asList("$YEAR", "$today.year");

private static final SerializableFileFilter UNSUPPORTED_JVM_FILES_FILTER = SerializableFileFilter.skipFilesNamed(
"package-info.java", "package-info.groovy", "module-info.java");

private final String licenseHeader;
private final boolean hasYearToken;
private final Pattern delimiterPattern;
private Pattern yearMatcherPattern;
private boolean hasYearToken;
private String licenseHeaderBeforeYearToken;
private String licenseHeaderAfterYearToken;
private String licenseHeaderWithYearTokenReplaced;
private final Pattern yearMatcherPattern;
private final String licenseHeaderBeforeYearToken;
private final String licenseHeaderAfterYearToken;
private final String licenseHeaderWithYearTokenReplaced;

/** Creates a FormatterStep which forces the start of each file to match a license header. */
public static FormatterStep createFromHeader(String licenseHeader, String delimiter) {
Expand Down Expand Up @@ -107,16 +111,34 @@ private LicenseHeaderStep(String licenseHeader, String delimiter, String yearSep
}
this.licenseHeader = licenseHeader;
this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE);
this.hasYearToken = licenseHeader.contains("$YEAR");
if (this.hasYearToken) {
int yearTokenIndex = licenseHeader.indexOf("$YEAR");
this.licenseHeaderBeforeYearToken = licenseHeader.substring(0, yearTokenIndex);
this.licenseHeaderAfterYearToken = licenseHeader.substring(yearTokenIndex + 5, licenseHeader.length());
this.licenseHeaderWithYearTokenReplaced = licenseHeader.replace("$YEAR", String.valueOf(YearMonth.now().getYear()));
this.yearMatcherPattern = Pattern.compile("[0-9]{4}(" + Pattern.quote(yearSeparator) + "[0-9]{4})?");

Optional<String> yearToken = getYearToken(licenseHeader);
this.hasYearToken = yearToken.isPresent();
if (hasYearToken) {
int yearTokenIndex = licenseHeader.indexOf(yearToken.get());
licenseHeaderBeforeYearToken = licenseHeader.substring(0, yearTokenIndex);
licenseHeaderAfterYearToken = licenseHeader.substring(yearTokenIndex + 5);
licenseHeaderWithYearTokenReplaced = licenseHeader.replace(yearToken.get(), String.valueOf(YearMonth.now().getYear()));
yearMatcherPattern = Pattern.compile("[0-9]{4}(" + Pattern.quote(yearSeparator) + "[0-9]{4})?");
} else {
licenseHeaderBeforeYearToken = null;
licenseHeaderAfterYearToken = null;
licenseHeaderWithYearTokenReplaced = null;
yearMatcherPattern = null;
}
}

/**
* Get the first place holder token being used in the
* license header for specifying the year
*
* @param licenseHeader String representation of the license header
* @return Matching value from YEAR_TOKENS or null if none exist
*/
private static Optional<String> getYearToken(String licenseHeader) {
return YEAR_TOKENS.stream().filter(licenseHeader::contains).findFirst();
}

/** Reads the license file from the given file. */
private LicenseHeaderStep(File licenseFile, Charset encoding, String delimiter, String yearSeparator) throws IOException {
this(new String(Files.readAllBytes(licenseFile.toPath()), encoding), delimiter, yearSeparator);
Expand Down
3 changes: 3 additions & 0 deletions plugin-gradle/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).

## [Unreleased]
### Added
* Enable IntelliJ-compatible token `$today.year` for specifying the year in license header files. ([#542](https://github.com/diffplug/spotless/pull/542))
### Fixed
* Eclipse-WTP formatter (web tools platform, not java) could encounter errors in parallel multiproject builds [#492](https://github.com/diffplug/spotless/issues/492). Fixed for Eclipse-WTP formatter Eclipse version 4.13.0 (default version).

## [3.27.2] - 2020-03-05
### Fixed
* Add tests to `SpecificFilesTest` to fix [#529](https://github.com/diffplug/spotless/issues/529)
* If you applied spotless to a subproject, but not to the root project, then on Gradle 6+ you would get the deprecation warning `Using method Project#afterEvaluate(Action) when the project is already evaluated has been deprecated.` This has now been fixed. ([#506](https://github.com/diffplug/spotless/issues/506))

Expand Down
4 changes: 1 addition & 3 deletions plugin-gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -523,9 +523,7 @@ to true.

## License header options

If the string contents of a licenseHeader step or the file contents of a licenseHeaderFile step contains a $YEAR token,
then in the end-result generated license headers which use this license header as a template, $YEAR will be replaced with the current year.

If the license header (specified with `licenseHeader` or `licenseHeaderFile`) contains `$YEAR` or `$today.year`, then that token will be replaced with the current 4-digit year.

For example:
```
Expand Down
2 changes: 2 additions & 0 deletions plugin-maven/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
### Added
* Enable IntelliJ-compatible token `$today.year` for specifying the year in license header files. ([#542](https://github.com/diffplug/spotless/pull/542))
### Fixed
* Fix scala and kotlin maven config documentation.
* Eclipse-WTP formatter (web tools platform, not java) could encounter errors in parallel multiproject builds [#492](https://github.com/diffplug/spotless/issues/492). Fixed for Eclipse-WTP formatter Eclipse version 4.13.0 (default version).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public class LicenseHeaderStepTest extends ResourceHarness {
private static final String KEY_FILE_WITH_LICENSE_AND_PLACEHOLDER = "license/FileWithLicenseHeaderAndPlaceholder.test";
// Licenses to test $YEAR token replacement
private static final String LICENSE_HEADER_YEAR = "This is a fake license, $YEAR. ACME corp.";
// License to test $today.year token replacement
private static final String LICENSE_HEADER_YEAR_INTELLIJ_TOKEN = "This is a fake license, $today.year. ACME corp.";
// Special case where the characters immediately before and after the year token are the same,
// start position of the second part might overlap the end position of the first part.
private static final String LICENSE_HEADER_YEAR_VARIANT = "This is a fake license. Copyright $YEAR ACME corp.";
Expand Down Expand Up @@ -82,6 +84,12 @@ public void should_apply_license_containing_YEAR_token() throws Throwable {
.test(fileWithLicenseContaining(" ACME corp."), fileWithLicenseContaining(LICENSE_HEADER_YEAR_VARIANT, currentYear()))
.test(fileWithLicenseContaining("This is a fake license. Copyright ACME corp."), fileWithLicenseContaining(LICENSE_HEADER_YEAR_VARIANT, currentYear()))
.test(fileWithLicenseContaining("This is a fake license. CopyrightACME corp."), fileWithLicenseContaining(LICENSE_HEADER_YEAR_VARIANT, currentYear()));

//Check when token is of the format $today.year
step = LicenseHeaderStep.createFromFile(createLicenseWith(LICENSE_HEADER_YEAR_INTELLIJ_TOKEN), StandardCharsets.UTF_8, LICENSE_HEADER_DELIMITER);

StepHarness.forStep(step)
.test(fileWithLicenseContaining(LICENSE_HEADER_YEAR_INTELLIJ_TOKEN), fileWithLicenseContaining(LICENSE_HEADER_YEAR_INTELLIJ_TOKEN, currentYear(), "$today.year"));
}

@Test
Expand Down Expand Up @@ -126,6 +134,10 @@ private String fileWithLicenseContaining(String license, String yearContent) thr
return getTestResource(KEY_FILE_WITH_LICENSE_AND_PLACEHOLDER).replace("__LICENSE_PLACEHOLDER__", license).replace("$YEAR", yearContent);
}

private String fileWithLicenseContaining(String license, String yearContent, String token) throws IOException {
return getTestResource(KEY_FILE_WITH_LICENSE_AND_PLACEHOLDER).replace("__LICENSE_PLACEHOLDER__", license).replace(token, yearContent);
}

private String currentYear() {
return String.valueOf(YearMonth.now().getYear());
}
Expand Down