From 373b6f40182646d8c29ef216e0c70a88ebce38b3 Mon Sep 17 00:00:00 2001 From: Sameer Balasubrahmanyam Date: Thu, 19 Mar 2020 18:56:00 -0700 Subject: [PATCH 1/5] Enable support for intelliJ placeholder for year in license header --- .../spotless/generic/LicenseHeaderStep.java | 27 +++++++++++++++---- plugin-gradle/README.md | 4 +-- .../generic/LicenseHeaderStepTest.java | 12 +++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java b/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java index 590701a816..da1956cb14 100644 --- a/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java +++ b/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java @@ -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; @@ -35,6 +38,7 @@ public final class LicenseHeaderStep implements Serializable { private static final String NAME = "licenseHeader"; private static final String DEFAULT_YEAR_DELIMITER = "-"; + private static final List 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"); @@ -107,16 +111,29 @@ 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"); + + if (getToken(licenseHeader).isPresent()) { + String token = getToken(licenseHeader).get(); + this.hasYearToken = true; + int yearTokenIndex = licenseHeader.indexOf(token); 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.licenseHeaderAfterYearToken = licenseHeader.substring(yearTokenIndex + 5); + this.licenseHeaderWithYearTokenReplaced = licenseHeader.replace(token, String.valueOf(YearMonth.now().getYear())); this.yearMatcherPattern = Pattern.compile("[0-9]{4}(" + Pattern.quote(yearSeparator) + "[0-9]{4})?"); } } + /** + * 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 Optional getToken(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); diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index 3436e32f9e..f3c2918beb 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -523,8 +523,8 @@ 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 string contents of a licenseHeader step or the file contents of a licenseHeaderFile step contains a $YEAR OR $today.year token, +then in the end-result generated license headers which use this license header as a template, $YEAR or $today.year will be replaced with the current year. For example: diff --git a/testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java b/testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java index 5d82767954..96b05ba5f9 100644 --- a/testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java @@ -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."; @@ -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 @@ -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()); } From 85741fada92de4ce93938c785ca9af5ebbf5f281 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Thu, 19 Mar 2020 21:11:25 -0700 Subject: [PATCH 2/5] Condense the documentation for the licenseHeader step. --- plugin-gradle/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugin-gradle/README.md b/plugin-gradle/README.md index f3c2918beb..245f7f4220 100644 --- a/plugin-gradle/README.md +++ b/plugin-gradle/README.md @@ -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 OR $today.year token, -then in the end-result generated license headers which use this license header as a template, $YEAR or $today.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: ``` From 8726a7b2abdcc9ffc209f4d402b51c86969b2046 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Thu, 19 Mar 2020 21:13:52 -0700 Subject: [PATCH 3/5] Minor refactor to LicenseHeaderStep to a more functional/immutable style. Makes it clear that an inner class ought to be used in the future, especially to support #496. --- .../spotless/generic/LicenseHeaderStep.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java b/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java index da1956cb14..384738af84 100644 --- a/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java +++ b/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java @@ -44,12 +44,12 @@ public final class LicenseHeaderStep implements Serializable { "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) { @@ -112,14 +112,19 @@ private LicenseHeaderStep(String licenseHeader, String delimiter, String yearSep this.licenseHeader = licenseHeader; this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE); - if (getToken(licenseHeader).isPresent()) { - String token = getToken(licenseHeader).get(); - this.hasYearToken = true; - int yearTokenIndex = licenseHeader.indexOf(token); - this.licenseHeaderBeforeYearToken = licenseHeader.substring(0, yearTokenIndex); - this.licenseHeaderAfterYearToken = licenseHeader.substring(yearTokenIndex + 5); - this.licenseHeaderWithYearTokenReplaced = licenseHeader.replace(token, String.valueOf(YearMonth.now().getYear())); - this.yearMatcherPattern = Pattern.compile("[0-9]{4}(" + Pattern.quote(yearSeparator) + "[0-9]{4})?"); + Optional 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; } } @@ -130,7 +135,7 @@ private LicenseHeaderStep(String licenseHeader, String delimiter, String yearSep * @param licenseHeader String representation of the license header * @return Matching value from YEAR_TOKENS or null if none exist */ - private Optional getToken(String licenseHeader) { + private static Optional getYearToken(String licenseHeader) { return YEAR_TOKENS.stream().filter(licenseHeader::contains).findFirst(); } From 61311ffde2d0121d7a91fd45d4eca9af27b01c4a Mon Sep 17 00:00:00 2001 From: Sameer Balasubrahmanyam Date: Fri, 20 Mar 2020 11:04:57 -0700 Subject: [PATCH 4/5] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index fd8f864f9b..a36f0fc4ab 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * We no longer publish `-SNAPSHOT` for every build to `master`, since we have good [JitPack integration](https://github.com/diffplug/spotless/blob/master/CONTRIBUTING.md#gradle---any-commit-in-a-public-github-repo-this-one-or-any-fork). ([#508](https://github.com/diffplug/spotless/pull/508)) * Improved how we use Spotless on itself. ([#509](https://github.com/diffplug/spotless/pull/509)) * Fix build warnings when building on Gradle 6+, bump build gradle to 6.2.2, and fix javadoc links. ([#536](https://github.com/diffplug/spotless/pull/536)) +* Enable IntelliJ compatible tokens for specifying the year in license header files ([#542](https://github.com/diffplug/spotless/pull/542)) ## [1.27.0] - 2020-01-01 * Ignored `KtLintStepTest`, because [gradle/gradle#11752](https://github.com/gradle/gradle/issues/11752) is causing too many CI failures. ([#499](https://github.com/diffplug/spotless/pull/499)) From 6ccc16df62b416543d2c765375c338652b716cd4 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Fri, 20 Mar 2020 16:04:05 -0700 Subject: [PATCH 5/5] Improve changelog message a bit, and add it to plugin-gradle and plugin-maven. --- CHANGES.md | 3 ++- plugin-gradle/CHANGES.md | 3 +++ plugin-maven/CHANGES.md | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index a36f0fc4ab..72ef499ec0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,13 +10,14 @@ 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)) * We no longer publish `-SNAPSHOT` for every build to `master`, since we have good [JitPack integration](https://github.com/diffplug/spotless/blob/master/CONTRIBUTING.md#gradle---any-commit-in-a-public-github-repo-this-one-or-any-fork). ([#508](https://github.com/diffplug/spotless/pull/508)) * Improved how we use Spotless on itself. ([#509](https://github.com/diffplug/spotless/pull/509)) * Fix build warnings when building on Gradle 6+, bump build gradle to 6.2.2, and fix javadoc links. ([#536](https://github.com/diffplug/spotless/pull/536)) -* Enable IntelliJ compatible tokens for specifying the year in license header files ([#542](https://github.com/diffplug/spotless/pull/542)) ## [1.27.0] - 2020-01-01 * Ignored `KtLintStepTest`, because [gradle/gradle#11752](https://github.com/gradle/gradle/issues/11752) is causing too many CI failures. ([#499](https://github.com/diffplug/spotless/pull/499)) diff --git a/plugin-gradle/CHANGES.md b/plugin-gradle/CHANGES.md index 09eda48b82..739ec3ef6d 100644 --- a/plugin-gradle/CHANGES.md +++ b/plugin-gradle/CHANGES.md @@ -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)) diff --git a/plugin-maven/CHANGES.md b/plugin-maven/CHANGES.md index 089e86e638..1998acb1a6 100644 --- a/plugin-maven/CHANGES.md +++ b/plugin-maven/CHANGES.md @@ -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).