View Javadoc
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 }