diff --git a/CHANGES.md b/CHANGES.md index e00b586ad5..b04f1913e0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format ( * **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)) * 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)). * This change also allows the gradle plugin to work with the remote buildcache (fixes [#280](https://github.com/diffplug/spotless/issues/280)). +* **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)) ## [1.34.1] - 2020-06-17 ### Changed 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 47d2289905..cd5ccebc91 100644 --- a/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java +++ b/lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java @@ -20,71 +20,127 @@ import java.io.IOException; import java.io.InputStream; import java.io.Serializable; -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.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Nullable; +import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.LineEnding; import com.diffplug.spotless.SerializableFileFilter; +import com.diffplug.spotless.ThrowingEx; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** Prefixes a license header before the package statement. */ -public final class LicenseHeaderStep implements Serializable { - private static final long serialVersionUID = 1L; +public final class LicenseHeaderStep { + public enum YearMode { + PRESERVE, UPDATE_TO_TODAY, SET_FROM_GIT + } - private static final String NAME = "licenseHeader"; - private static final String DEFAULT_YEAR_DELIMITER = "-"; - private static final List YEAR_TOKENS = Arrays.asList("$YEAR", "$today.year"); + public static LicenseHeaderStep headerDelimiter(String header, String delimiter) { + return headerDelimiter(() -> header, delimiter); + } - private static final SerializableFileFilter UNSUPPORTED_JVM_FILES_FILTER = SerializableFileFilter.skipFilesNamed( - "package-info.java", "package-info.groovy", "module-info.java"); + public static LicenseHeaderStep headerDelimiter(ThrowingEx.Supplier headerLazy, String delimiter) { + return new LicenseHeaderStep(headerLazy, delimiter, DEFAULT_YEAR_DELIMITER, () -> YearMode.PRESERVE); + } + + final ThrowingEx.Supplier headerLazy; + final String delimiter; + final String yearSeparator; + final Supplier yearMode; - /** Creates a FormatterStep which forces the start of each file to match a license header. */ - public static FormatterStep createFromHeader(String licenseHeader, String delimiter) { - return createFromHeader(licenseHeader, delimiter, DEFAULT_YEAR_DELIMITER); + private LicenseHeaderStep(ThrowingEx.Supplier headerLazy, String delimiter, String yearSeparator, Supplier yearMode) { + this.headerLazy = Objects.requireNonNull(headerLazy); + this.delimiter = Objects.requireNonNull(delimiter); + this.yearSeparator = Objects.requireNonNull(yearSeparator); + this.yearMode = Objects.requireNonNull(yearMode); } - public static FormatterStep createFromHeader(String licenseHeader, String delimiter, String yearSeparator) { - Objects.requireNonNull(licenseHeader, "licenseHeader"); - Objects.requireNonNull(delimiter, "delimiter"); - Objects.requireNonNull(yearSeparator, "yearSeparator"); - return FormatterStep.create(LicenseHeaderStep.NAME, - new LicenseHeaderStep(licenseHeader, delimiter, yearSeparator), - step -> step::format); + public LicenseHeaderStep withHeaderString(String header) { + return withHeaderLazy(() -> header); } - /** - * Creates a FormatterStep which forces the start of each file to match the license header - * contained in the given file. - */ - public static FormatterStep createFromFile(File licenseHeaderFile, Charset encoding, String delimiter) { - return createFromFile(licenseHeaderFile, encoding, delimiter, DEFAULT_YEAR_DELIMITER); + public LicenseHeaderStep withHeaderLazy(ThrowingEx.Supplier headerLazy) { + return new LicenseHeaderStep(headerLazy, delimiter, yearSeparator, yearMode); + } + + public LicenseHeaderStep withDelimiter(String delimiter) { + return new LicenseHeaderStep(headerLazy, delimiter, yearSeparator, yearMode); + } + + public LicenseHeaderStep withYearSeparator(String yearSeparator) { + return new LicenseHeaderStep(headerLazy, delimiter, yearSeparator, yearMode); + } + + public LicenseHeaderStep withYearMode(YearMode yearMode) { + return withYearModeLazy(() -> yearMode); + } + + public LicenseHeaderStep withYearModeLazy(Supplier yearMode) { + return new LicenseHeaderStep(headerLazy, delimiter, yearSeparator, yearMode); + } + + private static class SetFromGitFormatterFunc implements FormatterFunc { + private final Runtime runtime; + + private SetFromGitFormatterFunc(Runtime runtime) { + this.runtime = runtime; + } + + @Override + public String apply(String input, File source) throws Exception { + return runtime.setLicenseHeaderYearsFromGitHistory(input, source); + } + + @Override + public String apply(String input) throws Exception { + throw new UnsupportedOperationException(); + } } - /** - * Creates a FormatterStep which forces the start of each file to match the license header - * contained in the given file. - */ - public static FormatterStep createFromFile(File licenseHeaderFile, Charset encoding, String delimiter, String yearSeparator) { - Objects.requireNonNull(licenseHeaderFile, "licenseHeaderFile"); - Objects.requireNonNull(encoding, "encoding"); - Objects.requireNonNull(delimiter, "delimiter"); - Objects.requireNonNull(yearSeparator, "yearSeparator"); - return FormatterStep.createLazy(LicenseHeaderStep.NAME, - () -> new LicenseHeaderStep(new String(Files.readAllBytes(licenseHeaderFile.toPath()), encoding), delimiter, yearSeparator), - step -> step::format); + public FormatterStep build() { + if (yearMode.get() == YearMode.SET_FROM_GIT) { + return FormatterStep.createNeverUpToDateLazy(LicenseHeaderStep.name(), () -> { + boolean updateYear = false; // doesn't matter + Runtime step = new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear); + return new SetFromGitFormatterFunc(step); + }); + } else { + return FormatterStep.createLazy(LicenseHeaderStep.name(), () -> { + // by default, we should update the year if the user is using ratchetFrom + boolean updateYear; + switch (yearMode.get()) { + case PRESERVE: + updateYear = false; + break; + case UPDATE_TO_TODAY: + updateYear = true; + break; + case SET_FROM_GIT: + default: + throw new IllegalStateException(yearMode.toString()); + } + return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear); + }, step -> step::format); + } } + 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"); + public static String name() { return NAME; } @@ -97,189 +153,189 @@ public static SerializableFileFilter unsupportedJvmFilesFilter() { return UNSUPPORTED_JVM_FILES_FILTER; } - private final Pattern delimiterPattern; - private final String yearSepOrFull; - private final @Nullable String yearToday; - private final @Nullable String beforeYear; - private final @Nullable String afterYear; - private final boolean updateYearWithLatest; + public static final String spotlessSetLicenseHeaderYearsFromGitHistory = "spotlessSetLicenseHeaderYearsFromGitHistory"; - private LicenseHeaderStep(String licenseHeader, String delimiter, String yearSeparator) { - this(licenseHeader, delimiter, yearSeparator, false); + public static final String FLAG_SET_LICENSE_HEADER_YEARS_FROM_GIT_HISTORY() { + return spotlessSetLicenseHeaderYearsFromGitHistory; } - /** The license that we'd like enforced. */ - public LicenseHeaderStep(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest) { - if (delimiter.contains("\n")) { - throw new IllegalArgumentException("The delimiter must not contain any newlines."); - } - // sanitize the input license - licenseHeader = LineEnding.toUnix(licenseHeader); - if (!licenseHeader.endsWith("\n")) { - licenseHeader = licenseHeader + "\n"; - } - this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE); - - Optional yearToken = getYearToken(licenseHeader); - if (yearToken.isPresent()) { - yearToday = String.valueOf(YearMonth.now().getYear()); - int yearTokenIndex = licenseHeader.indexOf(yearToken.get()); - beforeYear = licenseHeader.substring(0, yearTokenIndex); - afterYear = licenseHeader.substring(yearTokenIndex + yearToken.get().length()); - yearSepOrFull = yearSeparator; - this.updateYearWithLatest = updateYearWithLatest; - } else { - yearToday = null; - beforeYear = null; - afterYear = null; - this.yearSepOrFull = licenseHeader; - this.updateYearWithLatest = false; + private static class Runtime implements Serializable { + private static final long serialVersionUID = 1475199492829130965L; + + private final Pattern delimiterPattern; + private final String yearSepOrFull; + private final @Nullable String yearToday; + private final @Nullable String beforeYear; + private final @Nullable String afterYear; + private final boolean updateYearWithLatest; + + /** The license that we'd like enforced. */ + private Runtime(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest) { + if (delimiter.contains("\n")) { + throw new IllegalArgumentException("The delimiter must not contain any newlines."); + } + // sanitize the input license + licenseHeader = LineEnding.toUnix(licenseHeader); + if (!licenseHeader.endsWith("\n")) { + licenseHeader = licenseHeader + "\n"; + } + this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE); + + Optional yearToken = getYearToken(licenseHeader); + if (yearToken.isPresent()) { + yearToday = String.valueOf(YearMonth.now().getYear()); + int yearTokenIndex = licenseHeader.indexOf(yearToken.get()); + beforeYear = licenseHeader.substring(0, yearTokenIndex); + afterYear = licenseHeader.substring(yearTokenIndex + yearToken.get().length()); + yearSepOrFull = yearSeparator; + this.updateYearWithLatest = updateYearWithLatest; + } else { + yearToday = null; + beforeYear = null; + afterYear = null; + this.yearSepOrFull = licenseHeader; + this.updateYearWithLatest = false; + } } - } - private static final Pattern patternYearSingle = Pattern.compile("[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 static Optional getYearToken(String licenseHeader) { - return YEAR_TOKENS.stream().filter(licenseHeader::contains).findFirst(); - } + private static final Pattern patternYearSingle = Pattern.compile("[0-9]{4}"); - /** Formats the given string. */ - public String format(String raw) { - Matcher contentMatcher = delimiterPattern.matcher(raw); - if (!contentMatcher.find()) { - throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern); - } else { - if (yearToday == null) { - // the no year case is easy - if (contentMatcher.start() == yearSepOrFull.length() && raw.startsWith(yearSepOrFull)) { - // if no change is required, return the raw string without - // creating any other new strings for maximum performance - return raw; - } else { - // otherwise we'll have to add the header - return yearSepOrFull + raw.substring(contentMatcher.start()); - } + /** + * 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 getYearToken(String licenseHeader) { + return YEAR_TOKENS.stream().filter(licenseHeader::contains).findFirst(); + } + + /** Formats the given string. */ + private String format(String raw) { + Matcher contentMatcher = delimiterPattern.matcher(raw); + if (!contentMatcher.find()) { + throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern); } else { - // the yes year case is a bit harder - int beforeYearIdx = raw.indexOf(beforeYear); - int afterYearIdx = raw.indexOf(afterYear, beforeYearIdx + beforeYear.length() + 1); - - if (beforeYearIdx >= 0 && afterYearIdx >= 0 && afterYearIdx + afterYear.length() <= contentMatcher.start()) { - boolean noPadding = beforeYearIdx == 0 && afterYearIdx + afterYear.length() == contentMatcher.start(); // allows fastpath return raw - String parsedYear = raw.substring(beforeYearIdx + beforeYear.length(), afterYearIdx); - if (parsedYear.equals(yearToday)) { - // it's good as is! - return noPadding ? raw : beforeYear + yearToday + afterYear + raw.substring(contentMatcher.start()); - } else if (patternYearSingle.matcher(parsedYear).matches()) { - if (updateYearWithLatest) { - // expand from `2004` to `2004-2020` - return beforeYear + parsedYear + yearSepOrFull + yearToday + afterYear + raw.substring(contentMatcher.start()); - } else { - // it's already good as a single year - return noPadding ? raw : beforeYear + parsedYear + afterYear + raw.substring(contentMatcher.start()); - } + if (yearToday == null) { + // the no year case is easy + if (contentMatcher.start() == yearSepOrFull.length() && raw.startsWith(yearSepOrFull)) { + // if no change is required, return the raw string without + // creating any other new strings for maximum performance + return raw; } else { - Matcher yearMatcher = patternYearSingle.matcher(parsedYear); - if (yearMatcher.find()) { - String firstYear = yearMatcher.group(); - String newYear; - String secondYear; + // otherwise we'll have to add the header + return yearSepOrFull + raw.substring(contentMatcher.start()); + } + } else { + // the yes year case is a bit harder + int beforeYearIdx = raw.indexOf(beforeYear); + int afterYearIdx = raw.indexOf(afterYear, beforeYearIdx + beforeYear.length() + 1); + + if (beforeYearIdx >= 0 && afterYearIdx >= 0 && afterYearIdx + afterYear.length() <= contentMatcher.start()) { + boolean noPadding = beforeYearIdx == 0 && afterYearIdx + afterYear.length() == contentMatcher.start(); // allows fastpath return raw + String parsedYear = raw.substring(beforeYearIdx + beforeYear.length(), afterYearIdx); + if (parsedYear.equals(yearToday)) { + // it's good as is! + return noPadding ? raw : beforeYear + yearToday + afterYear + raw.substring(contentMatcher.start()); + } else if (patternYearSingle.matcher(parsedYear).matches()) { if (updateYearWithLatest) { - secondYear = firstYear.equals(yearToday) ? null : yearToday; - } else if (yearMatcher.find(yearMatcher.end() + 1)) { - secondYear = yearMatcher.group(); + // expand from `2004` to `2004-2020` + return beforeYear + parsedYear + yearSepOrFull + yearToday + afterYear + raw.substring(contentMatcher.start()); } else { - secondYear = null; + // it's already good as a single year + return noPadding ? raw : beforeYear + parsedYear + afterYear + raw.substring(contentMatcher.start()); } - if (secondYear == null) { - newYear = firstYear; - } else { - newYear = firstYear + yearSepOrFull + secondYear; + } else { + Matcher yearMatcher = patternYearSingle.matcher(parsedYear); + if (yearMatcher.find()) { + String firstYear = yearMatcher.group(); + String newYear; + String secondYear; + if (updateYearWithLatest) { + secondYear = firstYear.equals(yearToday) ? null : yearToday; + } else if (yearMatcher.find(yearMatcher.end() + 1)) { + secondYear = yearMatcher.group(); + } else { + secondYear = null; + } + if (secondYear == null) { + newYear = firstYear; + } else { + newYear = firstYear + yearSepOrFull + secondYear; + } + return noPadding && newYear.equals(parsedYear) ? raw : beforeYear + newYear + afterYear + raw.substring(contentMatcher.start()); } - return noPadding && newYear.equals(parsedYear) ? raw : beforeYear + newYear + afterYear + raw.substring(contentMatcher.start()); } } + // at worst, we just say that it was made today + return beforeYear + yearToday + afterYear + raw.substring(contentMatcher.start()); } - // at worst, we just say that it was made today - return beforeYear + yearToday + afterYear + raw.substring(contentMatcher.start()); } } - } - - public static final String spotlessSetLicenseHeaderYearsFromGitHistory = "spotlessSetLicenseHeaderYearsFromGitHistory"; - - public static final String FLAG_SET_LICENSE_HEADER_YEARS_FROM_GIT_HISTORY() { - return spotlessSetLicenseHeaderYearsFromGitHistory; - } - /** Sets copyright years on the given file by finding the oldest and most recent commits throughout git history. */ - public String setLicenseHeaderYearsFromGitHistory(String raw, File file) throws IOException { - if (yearToday == null) { - return raw; - } - Matcher contentMatcher = delimiterPattern.matcher(raw); - if (!contentMatcher.find()) { - throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern); - } + /** Sets copyright years on the given file by finding the oldest and most recent commits throughout git history. */ + private String setLicenseHeaderYearsFromGitHistory(String raw, File file) throws IOException { + if (yearToday == null) { + return raw; + } + Matcher contentMatcher = delimiterPattern.matcher(raw); + if (!contentMatcher.find()) { + throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern); + } - String oldYear; - try { - oldYear = parseYear("git log --follow --find-renames=40% --diff-filter=A", file); - } catch (IllegalArgumentException e) { - // Ideally, git log would always find the commit where it was added. - // For some reason, that is sometimes not possible - in that case, - // we'll settle for just the most recent, even if it was just a modification. - oldYear = parseYear("git log --follow --find-renames=40% --reverse", file); - } - String newYear = parseYear("git log --max-count=1", file); - String yearRange; - if (oldYear.equals(newYear)) { - yearRange = oldYear; - } else { - yearRange = oldYear + yearSepOrFull + newYear; + String oldYear; + try { + oldYear = parseYear("git log --follow --find-renames=40% --diff-filter=A", file); + } catch (IllegalArgumentException e) { + // Ideally, git log would always find the commit where it was added. + // For some reason, that is sometimes not possible - in that case, + // we'll settle for just the most recent, even if it was just a modification. + oldYear = parseYear("git log --follow --find-renames=40% --reverse", file); + } + String newYear = parseYear("git log --max-count=1", file); + String yearRange; + if (oldYear.equals(newYear)) { + yearRange = oldYear; + } else { + yearRange = oldYear + yearSepOrFull + newYear; + } + return beforeYear + yearRange + afterYear + raw.substring(contentMatcher.start()); } - return beforeYear + yearRange + afterYear + raw.substring(contentMatcher.start()); - } - private static String parseYear(String cmd, File file) throws IOException { - String fullCmd = cmd + " " + file.getAbsolutePath(); - ProcessBuilder builder = new ProcessBuilder().directory(file.getParentFile()); - if (LineEnding.nativeIsWin()) { - builder.command("cmd", "/c", fullCmd); - } else { - builder.command("bash", "-c", fullCmd); - } - Process process = builder.start(); - String output = drain(process.getInputStream()); - String error = drain(process.getErrorStream()); - if (!error.isEmpty()) { - throw new IllegalArgumentException("Error for command '" + fullCmd + "':\n" + error); - } - Matcher matcher = FIND_YEAR.matcher(output); - if (matcher.find()) { - return matcher.group(1); - } else { - throw new IllegalArgumentException("Unable to parse date from command '" + fullCmd + "':\n" + output); + private static String parseYear(String cmd, File file) throws IOException { + String fullCmd = cmd + " " + file.getAbsolutePath(); + ProcessBuilder builder = new ProcessBuilder().directory(file.getParentFile()); + if (LineEnding.nativeIsWin()) { + builder.command("cmd", "/c", fullCmd); + } else { + builder.command("bash", "-c", fullCmd); + } + Process process = builder.start(); + String output = drain(process.getInputStream()); + String error = drain(process.getErrorStream()); + if (!error.isEmpty()) { + throw new IllegalArgumentException("Error for command '" + fullCmd + "':\n" + error); + } + Matcher matcher = FIND_YEAR.matcher(output); + if (matcher.find()) { + return matcher.group(1); + } else { + throw new IllegalArgumentException("Unable to parse date from command '" + fullCmd + "':\n" + output); + } } - } - private static final Pattern FIND_YEAR = Pattern.compile("Date: .* ([0-9]{4}) "); + private static final Pattern FIND_YEAR = Pattern.compile("Date: .* ([0-9]{4}) "); - @SuppressFBWarnings("DM_DEFAULT_ENCODING") - private static String drain(InputStream stream) throws IOException { - ByteArrayOutputStream output = new ByteArrayOutputStream(); - byte[] buf = new byte[1024]; - int numRead; - while ((numRead = stream.read(buf)) != -1) { - output.write(buf, 0, numRead); + @SuppressFBWarnings("DM_DEFAULT_ENCODING") + private static String drain(InputStream stream) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + int numRead; + while ((numRead = stream.read(buf)) != -1) { + output.write(buf, 0, numRead); + } + return new String(output.toByteArray()); } - return new String(output.toByteArray()); } } diff --git a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java index 3eb14d6a08..b1158c46c0 100644 --- a/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java +++ b/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java @@ -18,7 +18,6 @@ import static com.diffplug.gradle.spotless.PluginGradlePreconditions.requireElementsNonNull; import java.io.File; -import java.io.IOException; import java.io.Serializable; import java.nio.charset.Charset; import java.nio.file.Files; @@ -47,6 +46,7 @@ import com.diffplug.spotless.generic.EndWithNewlineStep; import com.diffplug.spotless.generic.IndentStep; import com.diffplug.spotless.generic.LicenseHeaderStep; +import com.diffplug.spotless.generic.LicenseHeaderStep.YearMode; import com.diffplug.spotless.generic.ReplaceRegexStep; import com.diffplug.spotless.generic.ReplaceStep; import com.diffplug.spotless.generic.TrimTrailingWhitespaceStep; @@ -443,13 +443,12 @@ public void indentWithTabs() { * For most language-specific formats (e.g. java, scala, etc.) you can omit the second `delimiter` argument, because it is supplied * automatically ({@link HasBuiltinDelimiterForLicense}). */ - public abstract class LicenseHeaderConfig { - String delimiter; - String yearSeparator = LicenseHeaderStep.defaultYearDelimiter(); + public class LicenseHeaderConfig { + LicenseHeaderStep builder; Boolean updateYearWithLatest = null; - public LicenseHeaderConfig(String delimiter) { - this.delimiter = Objects.requireNonNull(delimiter, "delimiter"); + public LicenseHeaderConfig(LicenseHeaderStep builder) { + this.builder = builder; } /** @@ -457,7 +456,7 @@ public LicenseHeaderConfig(String delimiter) { * Spotless will look for a line that starts with this regular expression pattern to know what the "top" is. */ public LicenseHeaderConfig delimiter(String delimiter) { - this.delimiter = Objects.requireNonNull(delimiter, "delimiter"); + builder = builder.withDelimiter(delimiter); replaceStep(createStep()); return this; } @@ -467,7 +466,7 @@ public LicenseHeaderConfig delimiter(String delimiter) { * The characters used to separate the first and last years in multi years patterns. */ public LicenseHeaderConfig yearSeparator(String yearSeparator) { - this.yearSeparator = Objects.requireNonNull(yearSeparator, "yearSeparator"); + builder = builder.withYearSeparator(yearSeparator); replaceStep(createStep()); return this; } @@ -483,61 +482,15 @@ public LicenseHeaderConfig updateYearWithLatest(boolean updateYearWithLatest) { return this; } - protected abstract String licenseHeader() throws IOException; - FormatterStep createStep() { - if ("true".equals(spotless.project.findProperty(LicenseHeaderStep.FLAG_SET_LICENSE_HEADER_YEARS_FROM_GIT_HISTORY()))) { - return FormatterStep.createNeverUpToDateLazy(LicenseHeaderStep.name(), () -> { - boolean updateYear = false; // doesn't matter - LicenseHeaderStep step = new LicenseHeaderStep(licenseHeader(), delimiter, yearSeparator, updateYear); - return new FormatterFunc() { - @Override - public String apply(String input, File source) throws Exception { - return step.setLicenseHeaderYearsFromGitHistory(input, source); - } - - @Override - public String apply(String input) throws Exception { - throw new UnsupportedOperationException(); - } - }; - }); - } else { - return FormatterStep.createLazy(LicenseHeaderStep.name(), () -> { - // by default, we should update the year if the user is using ratchetFrom + return builder.withYearModeLazy(() -> { + if ("true".equals(spotless.project.findProperty(LicenseHeaderStep.FLAG_SET_LICENSE_HEADER_YEARS_FROM_GIT_HISTORY()))) { + return YearMode.SET_FROM_GIT; + } else { boolean updateYear = updateYearWithLatest == null ? getRatchetFrom() != null : updateYearWithLatest; - return new LicenseHeaderStep(licenseHeader(), delimiter, yearSeparator, updateYear); - }, step -> step::format); - } - } - } - - private class LicenseStringHeaderConfig extends LicenseHeaderConfig { - private String header; - - LicenseStringHeaderConfig(String delimiter, String header) { - super(delimiter); - this.header = Objects.requireNonNull(header, "header"); - } - - @Override - protected String licenseHeader() { - return header; - } - } - - private class LicenseFileHeaderConfig extends LicenseHeaderConfig { - private Object headerFile; - - LicenseFileHeaderConfig(String delimiter, Object headerFile) { - super(delimiter); - this.headerFile = Objects.requireNonNull(headerFile, "headerFile"); - } - - @Override - protected String licenseHeader() throws IOException { - byte[] content = Files.readAllBytes(getProject().file(headerFile).toPath()); - return new String(content, getEncoding()); + return updateYear ? YearMode.UPDATE_TO_TODAY : YearMode.PRESERVE; + } + }).build(); } } @@ -548,7 +501,7 @@ protected String licenseHeader() throws IOException { * Spotless will look for a line that starts with this regular expression pattern to know what the "top" is. */ public LicenseHeaderConfig licenseHeader(String licenseHeader, String delimiter) { - LicenseHeaderConfig config = new LicenseStringHeaderConfig(delimiter, licenseHeader); + LicenseHeaderConfig config = new LicenseHeaderConfig(LicenseHeaderStep.headerDelimiter(licenseHeader, delimiter)); addStep(config.createStep()); return config; } @@ -560,7 +513,11 @@ public LicenseHeaderConfig licenseHeader(String licenseHeader, String delimiter) * Spotless will look for a line that starts with this regular expression pattern to know what the "top" is. */ public LicenseHeaderConfig licenseHeaderFile(Object licenseHeaderFile, String delimiter) { - LicenseHeaderConfig config = new LicenseFileHeaderConfig(delimiter, licenseHeaderFile); + LicenseHeaderConfig config = new LicenseHeaderConfig(LicenseHeaderStep.headerDelimiter(() -> { + File file = getProject().file(licenseHeaderFile); + byte[] data = Files.readAllBytes(file.toPath()); + return new String(data, getEncoding()); + }, delimiter)); addStep(config.createStep()); return config; } diff --git a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/LicenseHeaderTest.java b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/LicenseHeaderTest.java index d9594a3bcf..8e2b06ba43 100644 --- a/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/LicenseHeaderTest.java +++ b/plugin-gradle/src/test/java/com/diffplug/gradle/spotless/LicenseHeaderTest.java @@ -46,7 +46,7 @@ private void assertUnchanged(String year) throws IOException { private void assertTransform(String yearBefore, String yearAfter) throws IOException { setFile(TEST_JAVA).toContent("/** " + yearBefore + " */\n" + CONTENT); - gradleRunner().withArguments("spotlessApply", "--stacktrace").build(); + gradleRunner().withArguments("spotlessApply", "--stacktrace").forwardOutput().build(); assertFile(TEST_JAVA).hasContent("/** " + yearAfter + " */\n" + CONTENT); } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java index dc7a200000..ee2ae4fda0 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/LicenseHeader.java @@ -15,15 +15,14 @@ */ package com.diffplug.spotless.maven.generic; -import java.io.File; import java.io.IOException; import java.nio.file.Files; import org.apache.maven.plugins.annotations.Parameter; -import com.diffplug.spotless.FormatterFunc; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.generic.LicenseHeaderStep; +import com.diffplug.spotless.generic.LicenseHeaderStep.YearMode; import com.diffplug.spotless.maven.FormatterStepConfig; import com.diffplug.spotless.maven.FormatterStepFactory; @@ -45,32 +44,17 @@ public final FormatterStep newFormatterStep(FormatterStepConfig config) { throw new IllegalArgumentException("You need to specify 'delimiter'."); } if (file != null ^ content != null) { - FormatterStep unfiltered; + YearMode yearMode; if ("true".equals(config.spotlessSetLicenseHeaderYearsFromGitHistory().orElse(""))) { - unfiltered = FormatterStep.createNeverUpToDateLazy(LicenseHeaderStep.name(), () -> { - boolean updateYear = false; // doesn't matter - LicenseHeaderStep step = new LicenseHeaderStep(readFileOrContent(config), delimiterString, LicenseHeaderStep.defaultYearDelimiter(), updateYear); - return new FormatterFunc() { - @Override - public String apply(String input, File source) throws Exception { - return step.setLicenseHeaderYearsFromGitHistory(input, source); - } - - @Override - public String apply(String input) throws Exception { - throw new UnsupportedOperationException(); - } - }; - }); + yearMode = YearMode.SET_FROM_GIT; } else { - unfiltered = FormatterStep.createLazy(LicenseHeaderStep.name(), () -> { - // by default, we should update the year if the user is using ratchetFrom - boolean updateYear = config.getRatchetFrom().isPresent(); - String header = readFileOrContent(config); - return new LicenseHeaderStep(header, delimiterString, LicenseHeaderStep.defaultYearDelimiter(), updateYear); - }, step -> step::format); + boolean updateYear = config.getRatchetFrom().isPresent(); + yearMode = updateYear ? YearMode.UPDATE_TO_TODAY : YearMode.PRESERVE; } - return unfiltered.filterByFile(LicenseHeaderStep.unsupportedJvmFilesFilter()); + return LicenseHeaderStep.headerDelimiter(() -> readFileOrContent(config), delimiterString) + .withYearMode(yearMode) + .build() + .filterByFile(LicenseHeaderStep.unsupportedJvmFilesFilter()); } else { throw new IllegalArgumentException("Must specify exactly one of 'file' or 'content'."); } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/generic/LicenseHeaderRatchetTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/generic/LicenseHeaderRatchetTest.java new file mode 100644 index 0000000000..4eea01581d --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/generic/LicenseHeaderRatchetTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2020 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.spotless.maven.generic; + +import java.io.IOException; +import java.time.YearMonth; + +import org.eclipse.jgit.api.Git; +import org.junit.Test; + +import com.diffplug.spotless.maven.MavenIntegrationHarness; + +public class LicenseHeaderRatchetTest extends MavenIntegrationHarness { + private static final String NOW = String.valueOf(YearMonth.now().getYear()); + + private static final String TEST_JAVA = "src/main/java/pkg/Test.java"; + private static final String CONTENT = "package pkg;\npublic class Test {}"; + + private void setRatchetFrom(String ratchetFrom) throws IOException { + writePomWithJavaSteps( + "", + " /** $YEAR */", + "", + ratchetFrom); + } + + private void assertUnchanged(String year) throws Exception { + assertTransform(year, year); + } + + private void assertTransform(String yearBefore, String yearAfter) throws Exception { + setFile(TEST_JAVA).toContent("/** " + yearBefore + " */\n" + CONTENT); + mavenRunner().withArguments("spotless:apply").runNoError(); + assertFile(TEST_JAVA).hasContent("/** " + yearAfter + " */\n" + CONTENT); + } + + private void testSuiteUpdateWithLatest(boolean update) throws Exception { + if (update) { + assertTransform("2003", "2003-" + NOW); + assertTransform("2003-2005", "2003-" + NOW); + } else { + assertUnchanged("2003"); + assertUnchanged("2003-2005"); + } + assertUnchanged(NOW); + assertTransform("", NOW); + } + + @Test + public void normal() throws Exception { + setRatchetFrom(""); + testSuiteUpdateWithLatest(false); + } + + @Test + public void ratchetFrom() throws Exception { + try (Git git = Git.init().setDirectory(rootFolder()).call()) { + git.commit().setMessage("First commit").call(); + } + setRatchetFrom("HEAD"); + testSuiteUpdateWithLatest(true); + } +} diff --git a/testlib/src/test/java/com/diffplug/spotless/cpp/CppDefaultsTest.java b/testlib/src/test/java/com/diffplug/spotless/cpp/CppDefaultsTest.java index 3dd07c3da5..d6cd279b99 100644 --- a/testlib/src/test/java/com/diffplug/spotless/cpp/CppDefaultsTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/cpp/CppDefaultsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 DiffPlug + * Copyright 2016-2020 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ public class CppDefaultsTest extends ResourceHarness { @Test public void testDelimiterExpr() throws Exception { final String header = "/*My tests header*/"; - FormatterStep step = LicenseHeaderStep.createFromHeader(header, CppDefaults.DELIMITER_EXPR); + FormatterStep step = LicenseHeaderStep.headerDelimiter(header, CppDefaults.DELIMITER_EXPR).build(); final File dummyFile = setFile("src/main/cpp/file1.dummy").toContent(""); for (String testSource : Arrays.asList( "//Accpet multiple spaces between composed term.@using namespace std;", diff --git a/testlib/src/test/java/com/diffplug/spotless/css/CssDefaultsTest.java b/testlib/src/test/java/com/diffplug/spotless/css/CssDefaultsTest.java index 21cf735fa0..006a5f64b5 100644 --- a/testlib/src/test/java/com/diffplug/spotless/css/CssDefaultsTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/css/CssDefaultsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 DiffPlug + * Copyright 2016-2020 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ public class CssDefaultsTest extends ResourceHarness { @Test public void testDelimiterExpr() throws Exception { final String header = "/*My tests header*/"; - FormatterStep step = LicenseHeaderStep.createFromHeader(header, CssDefaults.DELIMITER_EXPR); + FormatterStep step = LicenseHeaderStep.headerDelimiter(header, CssDefaults.DELIMITER_EXPR).build(); final File dummyFile = setFile("src/main/cpp/file1.dummy").toContent(""); for (String testSource : Arrays.asList( "/* Starts with element selector */@\np {", 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 2b0d2a4937..9ca2f12245 100644 --- a/testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/generic/LicenseHeaderStepTest.java @@ -17,7 +17,6 @@ import java.io.File; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.time.YearMonth; import org.junit.Assert; @@ -27,6 +26,7 @@ import com.diffplug.spotless.ResourceHarness; import com.diffplug.spotless.SerializableEqualityTester; import com.diffplug.spotless.StepHarness; +import com.diffplug.spotless.generic.LicenseHeaderStep.YearMode; public class LicenseHeaderStepTest extends ResourceHarness { private static final String KEY_LICENSE = "license/TestLicense"; @@ -51,19 +51,13 @@ public class LicenseHeaderStepTest extends ResourceHarness { @Test public void fromHeader() throws Throwable { - FormatterStep step = LicenseHeaderStep.createFromHeader(getTestResource(KEY_LICENSE), LICENSE_HEADER_DELIMITER); - assertOnResources(step, KEY_FILE_NOTAPPLIED, KEY_FILE_APPLIED); - } - - @Test - public void fromFile() throws Throwable { - FormatterStep step = LicenseHeaderStep.createFromFile(createTestFile(KEY_LICENSE), StandardCharsets.UTF_8, LICENSE_HEADER_DELIMITER); + FormatterStep step = LicenseHeaderStep.headerDelimiter(getTestResource(KEY_LICENSE), LICENSE_HEADER_DELIMITER).build(); assertOnResources(step, KEY_FILE_NOTAPPLIED, KEY_FILE_APPLIED); } @Test public void should_apply_license_containing_YEAR_token() throws Throwable { - StepHarness.forStep(LicenseHeaderStep.createFromHeader(licenseWith(HEADER_WITH_YEAR), LICENSE_HEADER_DELIMITER)) + StepHarness.forStep(LicenseHeaderStep.headerDelimiter(licenseWith(HEADER_WITH_YEAR), LICENSE_HEADER_DELIMITER).build()) .test(getTestResource(KEY_FILE_WITHOUT_LICENSE), fileContainingYear(HEADER_WITH_YEAR, currentYear())) .testUnaffected(fileContainingYear(HEADER_WITH_YEAR, currentYear())) .testUnaffected(fileContainingYear(HEADER_WITH_YEAR, "2003")) @@ -72,7 +66,7 @@ public void should_apply_license_containing_YEAR_token() throws Throwable { .test(fileContainingYear(HEADER_WITH_YEAR + "\n **/\n/* Something after license.", "2003"), fileContainingYear(HEADER_WITH_YEAR, "2003")) .test(fileContainingYear(HEADER_WITH_YEAR, "not a year"), fileContainingYear(HEADER_WITH_YEAR, currentYear())); // Check with variant - StepHarness.forStep(LicenseHeaderStep.createFromHeader(licenseWith(HEADER_WITH_YEAR_VARIANT), LICENSE_HEADER_DELIMITER)) + StepHarness.forStep(LicenseHeaderStep.headerDelimiter(licenseWith(HEADER_WITH_YEAR_VARIANT), LICENSE_HEADER_DELIMITER).build()) .test(getTestResource(KEY_FILE_WITHOUT_LICENSE), fileContainingYear(HEADER_WITH_YEAR_VARIANT, currentYear())) .testUnaffected(fileContainingYear(HEADER_WITH_YEAR_VARIANT, currentYear())) .test(fileContaining("This is a fake license. Copyright "), fileContainingYear(HEADER_WITH_YEAR_VARIANT, currentYear())) @@ -81,7 +75,7 @@ public void should_apply_license_containing_YEAR_token() throws Throwable { .test(fileContaining("This is a fake license. CopyrightACME corp."), fileContainingYear(HEADER_WITH_YEAR_VARIANT, currentYear())); //Check when token is of the format $today.year - StepHarness.forStep(LicenseHeaderStep.createFromHeader(licenseWith(HEADER_WITH_YEAR_INTELLIJ), LICENSE_HEADER_DELIMITER)) + StepHarness.forStep(LicenseHeaderStep.headerDelimiter(licenseWith(HEADER_WITH_YEAR_INTELLIJ), LICENSE_HEADER_DELIMITER).build()) .test(fileContaining(HEADER_WITH_YEAR_INTELLIJ), fileWithLicenseContaining(HEADER_WITH_YEAR_INTELLIJ, currentYear(), "$today.year")); } @@ -91,8 +85,9 @@ private String fileWithLicenseContaining(String license, String yearContent, Str @Test public void updateYearWithLatest() throws Throwable { - LicenseHeaderStep stepState = new LicenseHeaderStep(licenseWith(HEADER_WITH_YEAR), LICENSE_HEADER_DELIMITER, "-", true); - FormatterStep step = FormatterStep.create(LicenseHeaderStep.name(), stepState, s -> s::format); + FormatterStep step = LicenseHeaderStep.headerDelimiter(licenseWith(HEADER_WITH_YEAR), LICENSE_HEADER_DELIMITER) + .withYearMode(YearMode.UPDATE_TO_TODAY) + .build(); StepHarness.forStep(step) .testUnaffected(fileContainingYear(HEADER_WITH_YEAR, currentYear())) .test(fileContainingYear(HEADER_WITH_YEAR, "2003"), fileContainingYear(HEADER_WITH_YEAR, "2003-" + currentYear())) @@ -101,21 +96,21 @@ public void updateYearWithLatest() throws Throwable { @Test public void should_apply_license_containing_YEAR_token_with_non_default_year_separator() throws Throwable { - StepHarness.forStep(LicenseHeaderStep.createFromHeader(licenseWith(HEADER_WITH_YEAR), LICENSE_HEADER_DELIMITER, ", ")) + StepHarness.forStep(LicenseHeaderStep.headerDelimiter(licenseWith(HEADER_WITH_YEAR), LICENSE_HEADER_DELIMITER).withYearSeparator(", ").build()) .testUnaffected(fileContainingYear(HEADER_WITH_YEAR, "1990, 2015")) .test(fileContainingYear(HEADER_WITH_YEAR, "1990-2015"), fileContainingYear(HEADER_WITH_YEAR, "1990, 2015")); } @Test public void should_apply_license_containing_YEAR_token_with_special_character_in_year_separator() throws Throwable { - StepHarness.forStep(LicenseHeaderStep.createFromHeader(licenseWith(HEADER_WITH_YEAR), LICENSE_HEADER_DELIMITER, "(")) + StepHarness.forStep(LicenseHeaderStep.headerDelimiter(licenseWith(HEADER_WITH_YEAR), LICENSE_HEADER_DELIMITER).withYearSeparator("(").build()) .testUnaffected(fileContainingYear(HEADER_WITH_YEAR, "1990(2015")) .test(fileContainingYear(HEADER_WITH_YEAR, "1990-2015"), fileContainingYear(HEADER_WITH_YEAR, "1990(2015")); } @Test public void should_apply_license_containing_YEAR_token_with_custom_separator() throws Throwable { - StepHarness.forStep(LicenseHeaderStep.createFromHeader(licenseWith(HEADER_WITH_YEAR), LICENSE_HEADER_DELIMITER)) + StepHarness.forStep(LicenseHeaderStep.headerDelimiter(licenseWith(HEADER_WITH_YEAR), LICENSE_HEADER_DELIMITER).build()) .test(getTestResource(KEY_FILE_WITHOUT_LICENSE), fileContainingYear(HEADER_WITH_YEAR, currentYear())) .testUnaffected(fileContainingYear(HEADER_WITH_YEAR, currentYear())) .testUnaffected(fileContainingYear(HEADER_WITH_YEAR, "2003")) @@ -141,7 +136,7 @@ private String currentYear() { @Test public void efficient() throws Throwable { - FormatterStep step = LicenseHeaderStep.createFromHeader("LicenseHeader\n", "contentstart"); + FormatterStep step = LicenseHeaderStep.headerDelimiter("LicenseHeader\n", "contentstart").build(); String alreadyCorrect = "LicenseHeader\ncontentstart"; Assert.assertEquals(alreadyCorrect, step.format(alreadyCorrect, new File(""))); // If no change is required, it should return the exact same string for efficiency reasons @@ -151,7 +146,7 @@ public void efficient() throws Throwable { @Test public void sanitized() throws Throwable { // The sanitizer should add a \n - FormatterStep step = LicenseHeaderStep.createFromHeader("LicenseHeader", "contentstart"); + FormatterStep step = LicenseHeaderStep.headerDelimiter("LicenseHeader", "contentstart").build(); String alreadyCorrect = "LicenseHeader\ncontentstart"; Assert.assertEquals(alreadyCorrect, step.format(alreadyCorrect, new File(""))); Assert.assertSame(alreadyCorrect, step.format(alreadyCorrect, new File(""))); @@ -160,7 +155,7 @@ public void sanitized() throws Throwable { @Test public void sanitizerDoesntGoTooFar() throws Throwable { // if the user wants extra lines after the header, we shouldn't clobber them - FormatterStep step = LicenseHeaderStep.createFromHeader("LicenseHeader\n\n", "contentstart"); + FormatterStep step = LicenseHeaderStep.headerDelimiter("LicenseHeader\n\n", "contentstart").build(); String alreadyCorrect = "LicenseHeader\n\ncontentstart"; Assert.assertEquals(alreadyCorrect, step.format(alreadyCorrect, new File(""))); Assert.assertSame(alreadyCorrect, step.format(alreadyCorrect, new File(""))); @@ -169,35 +164,33 @@ public void sanitizerDoesntGoTooFar() throws Throwable { @Test public void equality() { new SerializableEqualityTester() { - String header = "LICENSE"; - String delimiter = "package"; - String yearSep = "-"; - boolean updateYearWithLatest = false; + LicenseHeaderStep builder = LicenseHeaderStep.headerDelimiter("LICENSE", "package") + .withYearSeparator("-") + .withYearMode(YearMode.PRESERVE); @Override protected void setupTest(API api) { api.areDifferentThan(); - delimiter = "crate"; + builder = builder.withDelimiter("crate"); api.areDifferentThan(); - header = "APACHE $YEAR"; + builder = builder.withHeaderString("APACHE $YEAR"); api.areDifferentThan(); - delimiter = "package"; + builder = builder.withDelimiter("package"); api.areDifferentThan(); - yearSep = " - "; + builder = builder.withYearSeparator(" - "); api.areDifferentThan(); - updateYearWithLatest = true; + builder = builder.withYearMode(YearMode.UPDATE_TO_TODAY); api.areDifferentThan(); } @Override protected FormatterStep create() { - LicenseHeaderStep stepState = new LicenseHeaderStep(header, delimiter, yearSep, updateYearWithLatest); - return FormatterStep.create(LicenseHeaderStep.name(), stepState, s -> s::format); + return builder.build(); } }.testEquals(); } diff --git a/testlib/src/test/java/com/diffplug/spotless/xml/XmlDefaultsTest.java b/testlib/src/test/java/com/diffplug/spotless/xml/XmlDefaultsTest.java index cbdf86e445..c0a9038406 100644 --- a/testlib/src/test/java/com/diffplug/spotless/xml/XmlDefaultsTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/xml/XmlDefaultsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 DiffPlug + * Copyright 2016-2020 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ public class XmlDefaultsTest extends ResourceHarness { @Test public void testDelimiterExpr() throws Exception { final String header = ""; - FormatterStep step = LicenseHeaderStep.createFromHeader(header, XmlDefaults.DELIMITER_EXPR); + FormatterStep step = LicenseHeaderStep.headerDelimiter(header, XmlDefaults.DELIMITER_EXPR).build(); final File dummyFile = setFile("src/main/file.dummy").toContent(""); for (String testSource : Arrays.asList( "@\n",