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