1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks.header;
21
22 import java.io.File;
23 import java.util.ArrayList;
24 import java.util.BitSet;
25 import java.util.List;
26 import java.util.regex.Pattern;
27 import java.util.regex.PatternSyntaxException;
28
29 import com.puppycrawl.tools.checkstyle.StatelessCheck;
30 import com.puppycrawl.tools.checkstyle.api.FileText;
31 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
32 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
33
34
35
36
37
38
39
40
41
42
43 @StatelessCheck
44 public class RegexpHeaderCheck extends AbstractHeaderCheck {
45
46
47
48
49
50 public static final String MSG_HEADER_MISSING = "header.missing";
51
52
53
54
55
56 public static final String MSG_HEADER_MISMATCH = "header.mismatch";
57
58
59 private static final String EMPTY_LINE_PATTERN = "^$";
60
61
62 private static final Pattern BLANK_LINE = Pattern.compile(EMPTY_LINE_PATTERN);
63
64
65 private final List<Pattern> headerRegexps = new ArrayList<>();
66
67
68 private BitSet multiLines = new BitSet();
69
70
71
72
73
74
75
76 public void setMultiLines(int... list) {
77 multiLines = TokenUtil.asBitSet(list);
78 }
79
80 @Override
81 protected void processFiltered(File file, FileText fileText) {
82 final int headerSize = getHeaderLines().size();
83 final int fileSize = fileText.size();
84
85 if (headerSize - multiLines.cardinality() > fileSize) {
86 log(1, MSG_HEADER_MISSING);
87 }
88 else {
89 int headerLineNo = 0;
90 int index;
91 for (index = 0; headerLineNo < headerSize && index < fileSize; index++) {
92 final String line = fileText.get(index);
93 boolean isMatch = isMatch(line, headerLineNo);
94 while (!isMatch && isMultiLine(headerLineNo)) {
95 headerLineNo++;
96 isMatch = headerLineNo == headerSize
97 || isMatch(line, headerLineNo);
98 }
99 if (!isMatch) {
100 log(index + 1, MSG_HEADER_MISMATCH, getHeaderLine(headerLineNo));
101 break;
102 }
103 if (!isMultiLine(headerLineNo)) {
104 headerLineNo++;
105 }
106 }
107 if (index == fileSize) {
108
109
110 logFirstSinglelineLine(headerLineNo, headerSize);
111 }
112 }
113 }
114
115
116
117
118
119
120
121
122 private String getHeaderLine(int headerLineNo) {
123 String line = getHeaderLines().get(headerLineNo);
124 if (line.isEmpty()) {
125 line = EMPTY_LINE_PATTERN;
126 }
127 return line;
128 }
129
130
131
132
133
134
135
136 private void logFirstSinglelineLine(int startHeaderLine, int headerSize) {
137 for (int lineNum = startHeaderLine; lineNum < headerSize; lineNum++) {
138 if (!isMultiLine(lineNum)) {
139 log(1, MSG_HEADER_MISSING);
140 break;
141 }
142 }
143 }
144
145
146
147
148
149
150
151
152 private boolean isMatch(String line, int headerLineNo) {
153 return headerRegexps.get(headerLineNo).matcher(line).find();
154 }
155
156
157
158
159
160
161
162 private boolean isMultiLine(int lineNo) {
163 return multiLines.get(lineNo + 1);
164 }
165
166 @Override
167 protected void postProcessHeaderLines() {
168 final List<String> headerLines = getHeaderLines();
169 for (String line : headerLines) {
170 try {
171 if (line.isEmpty()) {
172 headerRegexps.add(BLANK_LINE);
173 }
174 else {
175 headerRegexps.add(Pattern.compile(line));
176 }
177 }
178 catch (final PatternSyntaxException exc) {
179 throw new IllegalArgumentException("line "
180 + (headerRegexps.size() + 1)
181 + " in header specification"
182 + " is not a regular expression", exc);
183 }
184 }
185 }
186
187
188
189
190
191
192
193
194
195
196
197
198 @Override
199 public void setHeader(String header) {
200 if (!CommonUtil.isBlank(header)) {
201 if (!CommonUtil.isPatternValid(header)) {
202 throw new IllegalArgumentException("Unable to parse format: " + header);
203 }
204 super.setHeader(header);
205 }
206 }
207
208 }