Skip to content

Commit

Permalink
add a $YEAR as a supported variable in license
Browse files Browse the repository at this point in the history
This token is replaced by the current year in the following cases:

* the license is missing
* the license in not formatted
* the $YEAR is not like 1990 or 1990-2005
  • Loading branch information
baptistemesta committed Dec 19, 2017
1 parent 7401807 commit e80f34d
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.time.YearMonth;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand All @@ -35,6 +36,11 @@ public final class LicenseHeaderStep implements Serializable {

private final String licenseHeader;
private final Pattern delimiterPattern;
private Pattern yearMatcherPattern;
private boolean hasYearToken;
private String licenseHeaderBeforeYEARToken;
private String licenseHeaderAfterYEARToken;
private 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 @@ -74,6 +80,14 @@ private LicenseHeaderStep(String licenseHeader, String delimiter) {
}
this.licenseHeader = licenseHeader;
this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE);
hasYearToken = licenseHeader.contains("$YEAR");
if (hasYearToken) {
int yearTokenIndex = licenseHeader.indexOf("$YEAR");
licenseHeaderBeforeYEARToken = licenseHeader.substring(0, yearTokenIndex);
licenseHeaderAfterYEARToken = licenseHeader.substring(yearTokenIndex + 5, licenseHeader.length());
licenseHeaderWithYEARTokenReplaced = licenseHeader.replace("$YEAR", String.valueOf(YearMonth.now().getYear()));
this.yearMatcherPattern = Pattern.compile("[0-9]{4}(-[0-9]{4})?");
}
}

/** Reads the license file from the given file. */
Expand All @@ -87,7 +101,14 @@ public String format(String raw) {
if (!matcher.find()) {
throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern);
} else {
if (matcher.start() == licenseHeader.length() && raw.startsWith(licenseHeader)) {
if (hasYearToken) {
if (matchesLicenseWithYearToken(raw, matcher)) {
//that means we have the license like `licenseHeaderBeforeYEARToken 1990-2015 licenseHeaderAfterYEARToken`
return raw;
} else {
return licenseHeaderWithYEARTokenReplaced + raw.substring(matcher.start());
}
} else if (matcher.start() == licenseHeader.length() && raw.startsWith(licenseHeader)) {
// if no change is required, return the raw string without
// creating any other new strings for maximum performance
return raw;
Expand All @@ -97,4 +118,10 @@ public String format(String raw) {
}
}
}

private boolean matchesLicenseWithYearToken(String raw, Matcher matcher) {
int startOfTheSecondPart = raw.indexOf(licenseHeaderAfterYEARToken);
return (raw.startsWith(licenseHeaderBeforeYEARToken) && startOfTheSecondPart + licenseHeaderAfterYEARToken.length() == matcher.start())
&& yearMatcherPattern.matcher(raw.substring(licenseHeaderBeforeYEARToken.length(), startOfTheSecondPart)).matches();
}
}
26 changes: 26 additions & 0 deletions plugin-gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,32 @@ spotless {
}
```

<a name="license-header"></a>

## License header options

The license header can contains a `$YEAR` variable that will be replaced by the current year.

For example:
```
/* Licensed under Apache-2.0 $YEAR. */
```
will produce
```
/* Licensed under Apache-2.0 2017. */
```
if build is launched in 2017


The step will change the license according to the following rules
* It replace the license using the current year when
* The license is missing
* The license is not formatted correctly
* It will *not* replace the license when
* The year variable is already present and is a single year, e.g. `/* Licensed under Apache-2.0 1990. */`
* The year variable is already present and is a year span, e.g. `/* Licensed under Apache-2.0 1990-2003. */`


<a name="custom"></a>

## Custom rules
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
package com.diffplug.spotless.generic;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.YearMonth;

import com.diffplug.spotless.StepHarness;
import org.junit.Assert;
import org.junit.Test;

Expand All @@ -29,6 +32,11 @@ public class LicenseHeaderStepTest extends ResourceHarness {
private static final String KEY_LICENSE = "license/TestLicense";
private static final String KEY_FILE_NOTAPPLIED = "license/MissingLicense.test";
private static final String KEY_FILE_APPLIED = "license/HasLicense.test";
private static final String KEY_LICENSE_WITH_YEAR = "license/TestLicencseWithYear";
private static final String KEY_FILE_WITHOUT_LICENSE = "license/MissLicenseWithYear.test";
private static final String KEY_FILE_WITH_PREVIOUS_YEAR = "license/LicenseWithPreviousYear.test";
private static final String KEY_FILE_WITH_PREVIOUS_YEARS = "license/LicenseWithPreviousYears.test";
private static final String KEY_FILE_WITH_CURRENT_YEAR = "license/LicenseWithYear.test";

// If this constant changes, don't forget to change the similarly-named one in
// plugin-gradle/src/main/java/com/diffplug/gradle/spotless/JavaExtension.java as well
Expand All @@ -46,6 +54,27 @@ public void fromFile() throws Throwable {
assertOnResources(step, KEY_FILE_NOTAPPLIED, KEY_FILE_APPLIED);
}

@Test
public void should_apply_license_containing_YEAR_variable() throws Throwable {
FormatterStep step = LicenseHeaderStep.createFromFile(createTestFile(KEY_LICENSE_WITH_YEAR), StandardCharsets.UTF_8, LICENSE_HEADER_DELIMITER);


StepHarness.forStep(step)
.test(getTestResource(KEY_FILE_WITHOUT_LICENSE), getFileContentWithYEAR(currentYear()))
.testUnaffected(getFileContentWithYEAR(currentYear()))
.testUnaffected(getFileContentWithYEAR("2003"))
.testUnaffected(getFileContentWithYEAR("1990-2015"))
.test(getFileContentWithYEAR("not a year"), getFileContentWithYEAR(currentYear()));
}

private String getFileContentWithYEAR(String year) throws IOException {
return getTestResource(KEY_FILE_WITH_CURRENT_YEAR).replace("__YEAR_to_replace_in_tests__", year);
}

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

@Test
public void efficient() throws Throwable {
FormatterStep step = LicenseHeaderStep.createFromHeader("LicenseHeader\n", "contentstart");
Expand Down
40 changes: 40 additions & 0 deletions testlib/src/test/resources/license/LicenseWithYear.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (C) __YEAR_to_replace_in_tests__. ACME corp.
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation
* version 2.1 of the License.
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
**/
package com.acme;

import java.util.function.Function;


public class Java8Test {
public void doStuff() throws Exception {
Function<String, Integer> example = Integer::parseInt;
example.andThen(val -> {
return val + 2;
} );
SimpleEnum val = SimpleEnum.A;
switch (val) {
case A:
break;
case B:
break;
case C:
break;
default:
throw new Exception();
}
}

public enum SimpleEnum {
A, B, C;
}
}
28 changes: 28 additions & 0 deletions testlib/src/test/resources/license/MissLicenseWithYear.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.acme;

import java.util.function.Function;


public class Java8Test {
public void doStuff() throws Exception {
Function<String, Integer> example = Integer::parseInt;
example.andThen(val -> {
return val + 2;
} );
SimpleEnum val = SimpleEnum.A;
switch (val) {
case A:
break;
case B:
break;
case C:
break;
default:
throw new Exception();
}
}

public enum SimpleEnum {
A, B, C;
}
}
12 changes: 12 additions & 0 deletions testlib/src/test/resources/license/TestLicencseWithYear
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright (C) $YEAR. ACME corp.
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation
* version 2.1 of the License.
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
**/

0 comments on commit e80f34d

Please sign in to comment.