1 ///////////////////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3 // Copyright (C) 2001-2026 the original author or authors.
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ///////////////////////////////////////////////////////////////////////////////////////////////
19
20 package com.puppycrawl.tools.checkstyle.checks.regexp;
21
22 import java.util.Optional;
23 import java.util.regex.Pattern;
24
25 import com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter;
26
27 /**
28 * Options for a detector.
29 */
30 public final class DetectorOptions {
31
32 /**
33 * Flags to compile a regular expression with.
34 * See {@link Pattern#flags()}.
35 */
36 private int compileFlags;
37 /** Used for reporting violations. */
38 private AbstractViolationReporter reporter;
39 /**
40 * Format of the regular expression to check for.
41 */
42 private String format;
43 /** The message to report on detection. If blank, then use the format. */
44 private String message;
45 /** Minimum number of times regular expression should occur in a file. */
46 private int minimum;
47 /** Maximum number of times regular expression should occur in a file. */
48 private int maximum;
49 /** Whether to ignore case when matching. */
50 private boolean ignoreCase;
51 /** Used to determine whether to suppress a detected match. */
52 private MatchSuppressor suppressor;
53 /** Pattern created from format. Lazily initialized. */
54 private Pattern pattern;
55
56 /** Default constructor.*/
57 private DetectorOptions() {
58 }
59
60 /**
61 * Returns new Builder object.
62 *
63 * @return Builder object.
64 */
65 public static Builder newBuilder() {
66 return new DetectorOptions().new Builder();
67 }
68
69 /**
70 * Format of the regular expression.
71 *
72 * @return format of the regular expression.
73 */
74 public String getFormat() {
75 return format;
76 }
77
78 /**
79 * The violation reporter to use.
80 *
81 * @return the violation reporter to use.
82 */
83 public AbstractViolationReporter getReporter() {
84 return reporter;
85 }
86
87 /**
88 * The message to report violations with.
89 *
90 * @return the message to report violations with.
91 */
92 public String getMessage() {
93 return message;
94 }
95
96 /**
97 * The minimum number of allowed detections.
98 *
99 * @return the minimum number of allowed detections.
100 */
101 public int getMinimum() {
102 return minimum;
103 }
104
105 /**
106 * The maximum number of allowed detections.
107 *
108 * @return the maximum number of allowed detections.
109 */
110 public int getMaximum() {
111 return maximum;
112 }
113
114 /**
115 * The suppressor to use.
116 *
117 * @return the suppressor to use.
118 */
119 public MatchSuppressor getSuppressor() {
120 return suppressor;
121 }
122
123 /**
124 * The pattern to use when matching.
125 *
126 * @return the pattern to use when matching.
127 */
128 public Pattern getPattern() {
129 return pattern;
130 }
131
132 /** Class which implements Builder pattern to build DetectorOptions instance. */
133 public final class Builder {
134 /**
135 * Creates a new {@code Builder} instance.
136 */
137 public Builder() {
138 // no code by default
139 }
140
141 /**
142 * Specifies the violation reporter and returns Builder object.
143 *
144 * @param val for reporting violations.
145 * @return Builder object.
146 * @noinspection ReturnOfInnerClass
147 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
148 */
149 public Builder reporter(AbstractViolationReporter val) {
150 reporter = val;
151 return this;
152 }
153
154 /**
155 * Specifies the compile-flags to compile a regular expression with
156 * and returns Builder object.
157 *
158 * @param val the format to use when matching lines.
159 * @return Builder object.
160 * @noinspection ReturnOfInnerClass
161 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
162 */
163 public Builder compileFlags(int val) {
164 compileFlags = val;
165 return this;
166 }
167
168 /**
169 * Specifies the format to use when matching lines and returns Builder object.
170 *
171 * @param val the format to use when matching lines.
172 * @return Builder object.
173 * @noinspection ReturnOfInnerClass
174 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
175 */
176 public Builder format(String val) {
177 format = val;
178 return this;
179 }
180
181 /**
182 * Specifies message to use when reporting a match and returns Builder object.
183 *
184 * @param val message to use when reporting a match.
185 * @return Builder object.
186 * @noinspection ReturnOfInnerClass
187 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
188 */
189 public Builder message(String val) {
190 message = val;
191 return this;
192 }
193
194 /**
195 * Specifies the minimum allowed number of detections and returns Builder object.
196 *
197 * @param val the minimum allowed number of detections.
198 * @return Builder object.
199 * @noinspection ReturnOfInnerClass
200 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
201 */
202 public Builder minimum(int val) {
203 minimum = val;
204 return this;
205 }
206
207 /**
208 * Specifies the maximum allowed number of detections and returns Builder object.
209 *
210 * @param val the maximum allowed number of detections.
211 * @return Builder object.
212 * @noinspection ReturnOfInnerClass
213 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
214 */
215 public Builder maximum(int val) {
216 maximum = val;
217 return this;
218 }
219
220 /**
221 * Specifies whether to ignore case when matching and returns Builder object.
222 *
223 * @param val whether to ignore case when matching.
224 * @return Builder object.
225 * @noinspection ReturnOfInnerClass, BooleanParameter
226 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
227 * @noinspectionreason BooleanParameter - check fields are boolean
228 */
229 public Builder ignoreCase(boolean val) {
230 ignoreCase = val;
231 return this;
232 }
233
234 /**
235 * Specifies the suppressor to use and returns Builder object.
236 *
237 * @param val the suppressor to use.
238 * @return current instance
239 * @noinspection ReturnOfInnerClass
240 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
241 */
242 public Builder suppressor(MatchSuppressor val) {
243 suppressor = val;
244 return this;
245 }
246
247 /**
248 * Returns new DetectorOptions instance.
249 *
250 * @return DetectorOptions instance.
251 */
252 public DetectorOptions build() {
253 message = Optional.ofNullable(message).orElse("");
254 suppressor = Optional.ofNullable(suppressor).orElse(NeverSuppress.INSTANCE);
255 pattern = Optional.ofNullable(format).map(this::createPattern).orElse(null);
256 return DetectorOptions.this;
257 }
258
259 /**
260 * Creates pattern to use by DetectorOptions instance.
261 *
262 * @param formatValue the format to use.
263 * @return Pattern object.
264 */
265 private Pattern createPattern(String formatValue) {
266 int options = compileFlags;
267 if (ignoreCase) {
268 options |= Pattern.CASE_INSENSITIVE;
269 }
270 return Pattern.compile(formatValue, options);
271 }
272
273 }
274
275 }