forked from diffplug/spotless
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLicenseHeaderStep.java
More file actions
146 lines (131 loc) · 5.97 KB
/
LicenseHeaderStep.java
File metadata and controls
146 lines (131 loc) · 5.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
* Copyright 2016 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.generic;
import java.io.File;
import java.io.IOException;
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;
import com.diffplug.spotless.FormatterStep;
import com.diffplug.spotless.LineEnding;
/** Prefixes a license header before the package statement. */
public final class LicenseHeaderStep implements Serializable {
private static final long serialVersionUID = 1L;
private static final String NAME = "licenseHeader";
private static final String DEFAULT_YEAR_DELIMITER = "-";
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) {
return createFromHeader(licenseHeader, delimiter, DEFAULT_YEAR_DELIMITER);
}
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);
}
/**
* 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);
}
/**
* 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(licenseHeaderFile, encoding, delimiter, yearSeparator),
step -> step::format);
}
public static String name() {
return NAME;
}
public static String defaultYearDelimiter() {
return DEFAULT_YEAR_DELIMITER;
}
/** The license that we'd like enforced. */
private LicenseHeaderStep(String licenseHeader, String delimiter, String yearSeparator) {
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.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");
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.yearMatcherPattern = Pattern.compile("[0-9]{4}(" + Pattern.quote(yearSeparator) + "[0-9]{4})?");
}
}
/** 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);
}
/** Formats the given string. */
public String format(String raw) {
Matcher matcher = delimiterPattern.matcher(raw);
if (!matcher.find()) {
throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern);
} else {
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;
} else {
// otherwise we'll have to add the header
return licenseHeader + raw.substring(matcher.start());
}
}
}
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();
}
}