Skip to content

Commit 8e0a5d5

Browse files
authored
Merge pull request #628 from diffplug/feat/license-api
Refactor the public API of `LicenseHeaderStep`
2 parents ba3c126 + 2993f1a commit 8e0a5d5

File tree

10 files changed

+388
-321
lines changed

10 files changed

+388
-321
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
1818
* **BREAKING** `FileSignature` can no longer sign folders, only files. Signatures are now based only on filename (not path), size, and a content hash. It throws an error if a signature is attempted on a folder or on multiple files with different paths but the same filename - it never breaks silently. This change does not break any of Spotless' internal logic, so it is unlikely to affect any of Spotless' consumers either. ([#571](https://github.com/diffplug/spotless/pull/571))
1919
* This change allows the maven plugin to cache classloaders across subprojects when loading config resources from the classpath (fixes [#559](https://github.com/diffplug/spotless/issues/559)).
2020
* This change also allows the gradle plugin to work with the remote buildcache (fixes [#280](https://github.com/diffplug/spotless/issues/280)).
21+
* **BREAKING** Heavy refactor of the `LicenseHeaderStep` public API. Doesn't change internal behavior, but makes implementation of the gradle and maven plugins much easier. ([#628](https://github.com/diffplug/spotless/pull/628))
2122

2223
## [1.34.1] - 2020-06-17
2324
### Changed

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

+252-196
Large diffs are not rendered by default.

plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java

+20-63
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import static com.diffplug.gradle.spotless.PluginGradlePreconditions.requireElementsNonNull;
1919

2020
import java.io.File;
21-
import java.io.IOException;
2221
import java.io.Serializable;
2322
import java.nio.charset.Charset;
2423
import java.nio.file.Files;
@@ -47,6 +46,7 @@
4746
import com.diffplug.spotless.generic.EndWithNewlineStep;
4847
import com.diffplug.spotless.generic.IndentStep;
4948
import com.diffplug.spotless.generic.LicenseHeaderStep;
49+
import com.diffplug.spotless.generic.LicenseHeaderStep.YearMode;
5050
import com.diffplug.spotless.generic.ReplaceRegexStep;
5151
import com.diffplug.spotless.generic.ReplaceStep;
5252
import com.diffplug.spotless.generic.TrimTrailingWhitespaceStep;
@@ -443,21 +443,20 @@ public void indentWithTabs() {
443443
* For most language-specific formats (e.g. java, scala, etc.) you can omit the second `delimiter` argument, because it is supplied
444444
* automatically ({@link HasBuiltinDelimiterForLicense}).
445445
*/
446-
public abstract class LicenseHeaderConfig {
447-
String delimiter;
448-
String yearSeparator = LicenseHeaderStep.defaultYearDelimiter();
446+
public class LicenseHeaderConfig {
447+
LicenseHeaderStep builder;
449448
Boolean updateYearWithLatest = null;
450449

451-
public LicenseHeaderConfig(String delimiter) {
452-
this.delimiter = Objects.requireNonNull(delimiter, "delimiter");
450+
public LicenseHeaderConfig(LicenseHeaderStep builder) {
451+
this.builder = builder;
453452
}
454453

455454
/**
456455
* @param delimiter
457456
* Spotless will look for a line that starts with this regular expression pattern to know what the "top" is.
458457
*/
459458
public LicenseHeaderConfig delimiter(String delimiter) {
460-
this.delimiter = Objects.requireNonNull(delimiter, "delimiter");
459+
builder = builder.withDelimiter(delimiter);
461460
replaceStep(createStep());
462461
return this;
463462
}
@@ -467,7 +466,7 @@ public LicenseHeaderConfig delimiter(String delimiter) {
467466
* The characters used to separate the first and last years in multi years patterns.
468467
*/
469468
public LicenseHeaderConfig yearSeparator(String yearSeparator) {
470-
this.yearSeparator = Objects.requireNonNull(yearSeparator, "yearSeparator");
469+
builder = builder.withYearSeparator(yearSeparator);
471470
replaceStep(createStep());
472471
return this;
473472
}
@@ -483,61 +482,15 @@ public LicenseHeaderConfig updateYearWithLatest(boolean updateYearWithLatest) {
483482
return this;
484483
}
485484

486-
protected abstract String licenseHeader() throws IOException;
487-
488485
FormatterStep createStep() {
489-
if ("true".equals(spotless.project.findProperty(LicenseHeaderStep.FLAG_SET_LICENSE_HEADER_YEARS_FROM_GIT_HISTORY()))) {
490-
return FormatterStep.createNeverUpToDateLazy(LicenseHeaderStep.name(), () -> {
491-
boolean updateYear = false; // doesn't matter
492-
LicenseHeaderStep step = new LicenseHeaderStep(licenseHeader(), delimiter, yearSeparator, updateYear);
493-
return new FormatterFunc() {
494-
@Override
495-
public String apply(String input, File source) throws Exception {
496-
return step.setLicenseHeaderYearsFromGitHistory(input, source);
497-
}
498-
499-
@Override
500-
public String apply(String input) throws Exception {
501-
throw new UnsupportedOperationException();
502-
}
503-
};
504-
});
505-
} else {
506-
return FormatterStep.createLazy(LicenseHeaderStep.name(), () -> {
507-
// by default, we should update the year if the user is using ratchetFrom
486+
return builder.withYearModeLazy(() -> {
487+
if ("true".equals(spotless.project.findProperty(LicenseHeaderStep.FLAG_SET_LICENSE_HEADER_YEARS_FROM_GIT_HISTORY()))) {
488+
return YearMode.SET_FROM_GIT;
489+
} else {
508490
boolean updateYear = updateYearWithLatest == null ? getRatchetFrom() != null : updateYearWithLatest;
509-
return new LicenseHeaderStep(licenseHeader(), delimiter, yearSeparator, updateYear);
510-
}, step -> step::format);
511-
}
512-
}
513-
}
514-
515-
private class LicenseStringHeaderConfig extends LicenseHeaderConfig {
516-
private String header;
517-
518-
LicenseStringHeaderConfig(String delimiter, String header) {
519-
super(delimiter);
520-
this.header = Objects.requireNonNull(header, "header");
521-
}
522-
523-
@Override
524-
protected String licenseHeader() {
525-
return header;
526-
}
527-
}
528-
529-
private class LicenseFileHeaderConfig extends LicenseHeaderConfig {
530-
private Object headerFile;
531-
532-
LicenseFileHeaderConfig(String delimiter, Object headerFile) {
533-
super(delimiter);
534-
this.headerFile = Objects.requireNonNull(headerFile, "headerFile");
535-
}
536-
537-
@Override
538-
protected String licenseHeader() throws IOException {
539-
byte[] content = Files.readAllBytes(getProject().file(headerFile).toPath());
540-
return new String(content, getEncoding());
491+
return updateYear ? YearMode.UPDATE_TO_TODAY : YearMode.PRESERVE;
492+
}
493+
}).build();
541494
}
542495
}
543496

@@ -548,7 +501,7 @@ protected String licenseHeader() throws IOException {
548501
* Spotless will look for a line that starts with this regular expression pattern to know what the "top" is.
549502
*/
550503
public LicenseHeaderConfig licenseHeader(String licenseHeader, String delimiter) {
551-
LicenseHeaderConfig config = new LicenseStringHeaderConfig(delimiter, licenseHeader);
504+
LicenseHeaderConfig config = new LicenseHeaderConfig(LicenseHeaderStep.headerDelimiter(licenseHeader, delimiter));
552505
addStep(config.createStep());
553506
return config;
554507
}
@@ -560,7 +513,11 @@ public LicenseHeaderConfig licenseHeader(String licenseHeader, String delimiter)
560513
* Spotless will look for a line that starts with this regular expression pattern to know what the "top" is.
561514
*/
562515
public LicenseHeaderConfig licenseHeaderFile(Object licenseHeaderFile, String delimiter) {
563-
LicenseHeaderConfig config = new LicenseFileHeaderConfig(delimiter, licenseHeaderFile);
516+
LicenseHeaderConfig config = new LicenseHeaderConfig(LicenseHeaderStep.headerDelimiter(() -> {
517+
File file = getProject().file(licenseHeaderFile);
518+
byte[] data = Files.readAllBytes(file.toPath());
519+
return new String(data, getEncoding());
520+
}, delimiter));
564521
addStep(config.createStep());
565522
return config;
566523
}

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/LicenseHeaderTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ private void assertUnchanged(String year) throws IOException {
4646

4747
private void assertTransform(String yearBefore, String yearAfter) throws IOException {
4848
setFile(TEST_JAVA).toContent("/** " + yearBefore + " */\n" + CONTENT);
49-
gradleRunner().withArguments("spotlessApply", "--stacktrace").build();
49+
gradleRunner().withArguments("spotlessApply", "--stacktrace").forwardOutput().build();
5050
assertFile(TEST_JAVA).hasContent("/** " + yearAfter + " */\n" + CONTENT);
5151
}
5252

plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java

+9-25
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,14 @@
1515
*/
1616
package com.diffplug.spotless.maven.generic;
1717

18-
import java.io.File;
1918
import java.io.IOException;
2019
import java.nio.file.Files;
2120

2221
import org.apache.maven.plugins.annotations.Parameter;
2322

24-
import com.diffplug.spotless.FormatterFunc;
2523
import com.diffplug.spotless.FormatterStep;
2624
import com.diffplug.spotless.generic.LicenseHeaderStep;
25+
import com.diffplug.spotless.generic.LicenseHeaderStep.YearMode;
2726
import com.diffplug.spotless.maven.FormatterStepConfig;
2827
import com.diffplug.spotless.maven.FormatterStepFactory;
2928

@@ -45,32 +44,17 @@ public final FormatterStep newFormatterStep(FormatterStepConfig config) {
4544
throw new IllegalArgumentException("You need to specify 'delimiter'.");
4645
}
4746
if (file != null ^ content != null) {
48-
FormatterStep unfiltered;
47+
YearMode yearMode;
4948
if ("true".equals(config.spotlessSetLicenseHeaderYearsFromGitHistory().orElse(""))) {
50-
unfiltered = FormatterStep.createNeverUpToDateLazy(LicenseHeaderStep.name(), () -> {
51-
boolean updateYear = false; // doesn't matter
52-
LicenseHeaderStep step = new LicenseHeaderStep(readFileOrContent(config), delimiterString, LicenseHeaderStep.defaultYearDelimiter(), updateYear);
53-
return new FormatterFunc() {
54-
@Override
55-
public String apply(String input, File source) throws Exception {
56-
return step.setLicenseHeaderYearsFromGitHistory(input, source);
57-
}
58-
59-
@Override
60-
public String apply(String input) throws Exception {
61-
throw new UnsupportedOperationException();
62-
}
63-
};
64-
});
49+
yearMode = YearMode.SET_FROM_GIT;
6550
} else {
66-
unfiltered = FormatterStep.createLazy(LicenseHeaderStep.name(), () -> {
67-
// by default, we should update the year if the user is using ratchetFrom
68-
boolean updateYear = config.getRatchetFrom().isPresent();
69-
String header = readFileOrContent(config);
70-
return new LicenseHeaderStep(header, delimiterString, LicenseHeaderStep.defaultYearDelimiter(), updateYear);
71-
}, step -> step::format);
51+
boolean updateYear = config.getRatchetFrom().isPresent();
52+
yearMode = updateYear ? YearMode.UPDATE_TO_TODAY : YearMode.PRESERVE;
7253
}
73-
return unfiltered.filterByFile(LicenseHeaderStep.unsupportedJvmFilesFilter());
54+
return LicenseHeaderStep.headerDelimiter(() -> readFileOrContent(config), delimiterString)
55+
.withYearMode(yearMode)
56+
.build()
57+
.filterByFile(LicenseHeaderStep.unsupportedJvmFilesFilter());
7458
} else {
7559
throw new IllegalArgumentException("Must specify exactly one of 'file' or 'content'.");
7660
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2020 DiffPlug
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.maven.generic;
17+
18+
import java.io.IOException;
19+
import java.time.YearMonth;
20+
21+
import org.eclipse.jgit.api.Git;
22+
import org.junit.Test;
23+
24+
import com.diffplug.spotless.maven.MavenIntegrationHarness;
25+
26+
public class LicenseHeaderRatchetTest extends MavenIntegrationHarness {
27+
private static final String NOW = String.valueOf(YearMonth.now().getYear());
28+
29+
private static final String TEST_JAVA = "src/main/java/pkg/Test.java";
30+
private static final String CONTENT = "package pkg;\npublic class Test {}";
31+
32+
private void setRatchetFrom(String ratchetFrom) throws IOException {
33+
writePomWithJavaSteps(
34+
"<licenseHeader>",
35+
" <content>/** $YEAR */</content>",
36+
"</licenseHeader>",
37+
ratchetFrom);
38+
}
39+
40+
private void assertUnchanged(String year) throws Exception {
41+
assertTransform(year, year);
42+
}
43+
44+
private void assertTransform(String yearBefore, String yearAfter) throws Exception {
45+
setFile(TEST_JAVA).toContent("/** " + yearBefore + " */\n" + CONTENT);
46+
mavenRunner().withArguments("spotless:apply").runNoError();
47+
assertFile(TEST_JAVA).hasContent("/** " + yearAfter + " */\n" + CONTENT);
48+
}
49+
50+
private void testSuiteUpdateWithLatest(boolean update) throws Exception {
51+
if (update) {
52+
assertTransform("2003", "2003-" + NOW);
53+
assertTransform("2003-2005", "2003-" + NOW);
54+
} else {
55+
assertUnchanged("2003");
56+
assertUnchanged("2003-2005");
57+
}
58+
assertUnchanged(NOW);
59+
assertTransform("", NOW);
60+
}
61+
62+
@Test
63+
public void normal() throws Exception {
64+
setRatchetFrom("");
65+
testSuiteUpdateWithLatest(false);
66+
}
67+
68+
@Test
69+
public void ratchetFrom() throws Exception {
70+
try (Git git = Git.init().setDirectory(rootFolder()).call()) {
71+
git.commit().setMessage("First commit").call();
72+
}
73+
setRatchetFrom("<ratchetFrom>HEAD</ratchetFrom>");
74+
testSuiteUpdateWithLatest(true);
75+
}
76+
}

testlib/src/test/java/com/diffplug/spotless/cpp/CppDefaultsTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016 DiffPlug
2+
* Copyright 2016-2020 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,7 +31,7 @@ public class CppDefaultsTest extends ResourceHarness {
3131
@Test
3232
public void testDelimiterExpr() throws Exception {
3333
final String header = "/*My tests header*/";
34-
FormatterStep step = LicenseHeaderStep.createFromHeader(header, CppDefaults.DELIMITER_EXPR);
34+
FormatterStep step = LicenseHeaderStep.headerDelimiter(header, CppDefaults.DELIMITER_EXPR).build();
3535
final File dummyFile = setFile("src/main/cpp/file1.dummy").toContent("");
3636
for (String testSource : Arrays.asList(
3737
"//Accpet multiple spaces between composed term.@using namespace std;",

testlib/src/test/java/com/diffplug/spotless/css/CssDefaultsTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016 DiffPlug
2+
* Copyright 2016-2020 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ public class CssDefaultsTest extends ResourceHarness {
3333
@Test
3434
public void testDelimiterExpr() throws Exception {
3535
final String header = "/*My tests header*/";
36-
FormatterStep step = LicenseHeaderStep.createFromHeader(header, CssDefaults.DELIMITER_EXPR);
36+
FormatterStep step = LicenseHeaderStep.headerDelimiter(header, CssDefaults.DELIMITER_EXPR).build();
3737
final File dummyFile = setFile("src/main/cpp/file1.dummy").toContent("");
3838
for (String testSource : Arrays.asList(
3939
"/* Starts with element selector */@\np {",

0 commit comments

Comments
 (0)