Skip to content

Commit e19bc67

Browse files
committed
add support for skipping first few lines matching a pattern
1 parent 8d1467f commit e19bc67

File tree

2 files changed

+57
-18
lines changed

2 files changed

+57
-18
lines changed

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

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public static LicenseHeaderStep headerDelimiter(String header, String delimiter)
5151
}
5252

5353
public static LicenseHeaderStep headerDelimiter(ThrowingEx.Supplier<String> headerLazy, String delimiter) {
54-
return new LicenseHeaderStep(null, null, headerLazy, delimiter, DEFAULT_YEAR_DELIMITER, () -> YearMode.PRESERVE);
54+
return new LicenseHeaderStep(null, null, headerLazy, delimiter, DEFAULT_YEAR_DELIMITER, () -> YearMode.PRESERVE, null);
5555
}
5656

5757
final String name;
@@ -60,50 +60,56 @@ public static LicenseHeaderStep headerDelimiter(ThrowingEx.Supplier<String> head
6060
final String delimiter;
6161
final String yearSeparator;
6262
final Supplier<YearMode> yearMode;
63+
final @Nullable String skipLinesPattern;
6364

64-
private LicenseHeaderStep(@Nullable String name, @Nullable String contentPattern, ThrowingEx.Supplier<String> headerLazy, String delimiter, String yearSeparator, Supplier<YearMode> yearMode) {
65+
private LicenseHeaderStep(@Nullable String name, @Nullable String contentPattern, ThrowingEx.Supplier<String> headerLazy, String delimiter, String yearSeparator, Supplier<YearMode> yearMode, @Nullable String skipLinesPattern) {
6566
this.name = sanitizeName(name);
66-
this.contentPattern = sanitizeContentPattern(contentPattern);
67+
this.contentPattern = sanitizePattern(contentPattern);
6768
this.headerLazy = Objects.requireNonNull(headerLazy);
6869
this.delimiter = Objects.requireNonNull(delimiter);
6970
this.yearSeparator = Objects.requireNonNull(yearSeparator);
7071
this.yearMode = Objects.requireNonNull(yearMode);
72+
this.skipLinesPattern = sanitizePattern(skipLinesPattern);
7173
}
7274

7375
public String getName() {
7476
return name;
7577
}
7678

7779
public LicenseHeaderStep withName(String name) {
78-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
80+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesPattern);
7981
}
8082

8183
public LicenseHeaderStep withContentPattern(String contentPattern) {
82-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
84+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesPattern);
8385
}
8486

8587
public LicenseHeaderStep withHeaderString(String header) {
8688
return withHeaderLazy(() -> header);
8789
}
8890

8991
public LicenseHeaderStep withHeaderLazy(ThrowingEx.Supplier<String> headerLazy) {
90-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
92+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesPattern);
9193
}
9294

9395
public LicenseHeaderStep withDelimiter(String delimiter) {
94-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
96+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesPattern);
9597
}
9698

9799
public LicenseHeaderStep withYearSeparator(String yearSeparator) {
98-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
100+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesPattern);
99101
}
100102

101103
public LicenseHeaderStep withYearMode(YearMode yearMode) {
102104
return withYearModeLazy(() -> yearMode);
103105
}
104106

105107
public LicenseHeaderStep withYearModeLazy(Supplier<YearMode> yearMode) {
106-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
108+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesPattern);
109+
}
110+
111+
public LicenseHeaderStep withSkipLinesPattern(String skipLinesPattern) {
112+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesPattern);
107113
}
108114

109115
public FormatterStep build() {
@@ -112,7 +118,7 @@ public FormatterStep build() {
112118
if (yearMode.get() == YearMode.SET_FROM_GIT) {
113119
formatterStep = FormatterStep.createNeverUpToDateLazy(name, () -> {
114120
boolean updateYear = false; // doesn't matter
115-
Runtime runtime = new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear);
121+
Runtime runtime = new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesPattern);
116122
return FormatterFunc.needsFile(runtime::setLicenseHeaderYearsFromGitHistory);
117123
});
118124
} else {
@@ -130,7 +136,7 @@ public FormatterStep build() {
130136
default:
131137
throw new IllegalStateException(yearMode.toString());
132138
}
133-
return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear);
139+
return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesPattern);
134140
}, step -> step::format);
135141
}
136142

@@ -156,18 +162,18 @@ private String sanitizeName(@Nullable String name) {
156162
}
157163

158164
@Nullable
159-
private String sanitizeContentPattern(@Nullable String contentPattern) {
160-
if (contentPattern == null) {
161-
return contentPattern;
165+
private String sanitizePattern(@Nullable String pattern) {
166+
if (pattern == null) {
167+
return pattern;
162168
}
163169

164-
contentPattern = contentPattern.trim();
170+
pattern = pattern.trim();
165171

166-
if (contentPattern.isEmpty()) {
172+
if (pattern.isEmpty()) {
167173
return null;
168174
}
169175

170-
return contentPattern;
176+
return pattern;
171177
}
172178

173179
private static final String DEFAULT_NAME_PREFIX = LicenseHeaderStep.class.getName();
@@ -195,6 +201,7 @@ private static class Runtime implements Serializable {
195201
private static final long serialVersionUID = 1475199492829130965L;
196202

197203
private final Pattern delimiterPattern;
204+
private final @Nullable Pattern skipLinesPattern;
198205
private final String yearSepOrFull;
199206
private final @Nullable String yearToday;
200207
private final @Nullable String beforeYear;
@@ -203,7 +210,7 @@ private static class Runtime implements Serializable {
203210
private final boolean licenseHeaderWithRange;
204211

205212
/** The license that we'd like enforced. */
206-
private Runtime(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest) {
213+
private Runtime(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest, @Nullable String skipLinesPattern) {
207214
if (delimiter.contains("\n")) {
208215
throw new IllegalArgumentException("The delimiter must not contain any newlines.");
209216
}
@@ -213,6 +220,7 @@ private Runtime(String licenseHeader, String delimiter, String yearSeparator, bo
213220
licenseHeader = licenseHeader + "\n";
214221
}
215222
this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE);
223+
this.skipLinesPattern = skipLinesPattern == null ? null : Pattern.compile(skipLinesPattern);
216224

217225
Optional<String> yearToken = getYearToken(licenseHeader);
218226
if (yearToken.isPresent()) {
@@ -254,6 +262,31 @@ private static Optional<String> getYearToken(String licenseHeader) {
254262

255263
/** Formats the given string. */
256264
private String format(String raw) {
265+
if (skipLinesPattern == null) {
266+
return addOrUpdateLicenseHeader(raw);
267+
} else {
268+
String[] lines = raw.split("\n");
269+
StringBuilder skippedLinesBuilder = new StringBuilder();
270+
StringBuilder remainingLinesBuilder = new StringBuilder();
271+
boolean lastMatched = true;
272+
for (String line : lines) {
273+
if (lastMatched) {
274+
Matcher matcher = skipLinesPattern.matcher(line);
275+
if (matcher.find()) {
276+
skippedLinesBuilder.append(line).append('\n');
277+
} else {
278+
remainingLinesBuilder.append(line).append('\n');
279+
lastMatched = false;
280+
}
281+
} else {
282+
remainingLinesBuilder.append(line).append('\n');
283+
}
284+
}
285+
return skippedLinesBuilder + addOrUpdateLicenseHeader(remainingLinesBuilder.toString());
286+
}
287+
}
288+
289+
private String addOrUpdateLicenseHeader(String raw) {
257290
Matcher contentMatcher = delimiterPattern.matcher(raw);
258291
if (!contentMatcher.find()) {
259292
throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,12 @@ public LicenseHeaderConfig yearSeparator(String yearSeparator) {
462462
return this;
463463
}
464464

465+
public LicenseHeaderConfig skipLinesPattern(String skipLinesPattern) {
466+
builder = builder.withSkipLinesPattern(skipLinesPattern);
467+
replaceStep(createStep());
468+
return this;
469+
}
470+
465471
/**
466472
* @param updateYearWithLatest
467473
* Will turn {@code 2004} into {@code 2004-2020}, and {@code 2004-2019} into {@code 2004-2020}

0 commit comments

Comments
 (0)