001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2026 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018/////////////////////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.checks.regexp; 021 022import java.util.Optional; 023import java.util.regex.Pattern; 024 025import com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter; 026 027/** 028 * Options for a detector. 029 */ 030public final class DetectorOptions { 031 032 /** 033 * Flags to compile a regular expression with. 034 * See {@link Pattern#flags()}. 035 */ 036 private int compileFlags; 037 /** Used for reporting violations. */ 038 private AbstractViolationReporter reporter; 039 /** 040 * Format of the regular expression to check for. 041 */ 042 private String format; 043 /** The message to report on detection. If blank, then use the format. */ 044 private String message; 045 /** Minimum number of times regular expression should occur in a file. */ 046 private int minimum; 047 /** Maximum number of times regular expression should occur in a file. */ 048 private int maximum; 049 /** Whether to ignore case when matching. */ 050 private boolean ignoreCase; 051 /** Used to determine whether to suppress a detected match. */ 052 private MatchSuppressor suppressor; 053 /** Pattern created from format. Lazily initialized. */ 054 private Pattern pattern; 055 /** Which capturing group to use for violation reporting. */ 056 private int reportGroup; 057 058 /** Default constructor.*/ 059 private DetectorOptions() { 060 } 061 062 /** 063 * Returns new Builder object. 064 * 065 * @return Builder object. 066 */ 067 public static Builder newBuilder() { 068 return new DetectorOptions().new Builder(); 069 } 070 071 /** 072 * Format of the regular expression. 073 * 074 * @return format of the regular expression. 075 */ 076 public String getFormat() { 077 return format; 078 } 079 080 /** 081 * The violation reporter to use. 082 * 083 * @return the violation reporter to use. 084 */ 085 public AbstractViolationReporter getReporter() { 086 return reporter; 087 } 088 089 /** 090 * The message to report violations with. 091 * 092 * @return the message to report violations with. 093 */ 094 public String getMessage() { 095 return message; 096 } 097 098 /** 099 * The minimum number of allowed detections. 100 * 101 * @return the minimum number of allowed detections. 102 */ 103 public int getMinimum() { 104 return minimum; 105 } 106 107 /** 108 * The maximum number of allowed detections. 109 * 110 * @return the maximum number of allowed detections. 111 */ 112 public int getMaximum() { 113 return maximum; 114 } 115 116 /** 117 * The suppressor to use. 118 * 119 * @return the suppressor to use. 120 */ 121 public MatchSuppressor getSuppressor() { 122 return suppressor; 123 } 124 125 /** 126 * The pattern to use when matching. 127 * 128 * @return the pattern to use when matching. 129 */ 130 public Pattern getPattern() { 131 return pattern; 132 } 133 134 /** 135 * Which capturing group to use for violation reporting. 136 * 137 * @return the capturing group to use for violation reporting. 138 */ 139 public int getReportGroup() { 140 return reportGroup; 141 } 142 143 /** Class which implements Builder pattern to build DetectorOptions instance. */ 144 public final class Builder { 145 146 /** 147 * Specifies the violation reporter and returns Builder object. 148 * 149 * @param val for reporting violations. 150 * @return Builder object. 151 * @noinspection ReturnOfInnerClass 152 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 153 */ 154 public Builder reporter(AbstractViolationReporter val) { 155 reporter = val; 156 return this; 157 } 158 159 /** 160 * Specifies which capturing group to use for violation reporting. 161 * 162 * @param val the capturing group to use. 163 * @return Builder object. 164 * @noinspection ReturnOfInnerClass 165 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 166 */ 167 public Builder reportGroup(int val) { 168 reportGroup = val; 169 return this; 170 } 171 172 /** 173 * Specifies the compile-flags to compile a regular expression with 174 * and returns Builder object. 175 * 176 * @param val the format to use when matching lines. 177 * @return Builder object. 178 * @noinspection ReturnOfInnerClass 179 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 180 */ 181 public Builder compileFlags(int val) { 182 compileFlags = val; 183 return this; 184 } 185 186 /** 187 * Specifies the format to use when matching lines and returns Builder object. 188 * 189 * @param val the format to use when matching lines. 190 * @return Builder object. 191 * @noinspection ReturnOfInnerClass 192 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 193 */ 194 public Builder format(String val) { 195 format = val; 196 return this; 197 } 198 199 /** 200 * Specifies message to use when reporting a match and returns Builder object. 201 * 202 * @param val message to use when reporting a match. 203 * @return Builder object. 204 * @noinspection ReturnOfInnerClass 205 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 206 */ 207 public Builder message(String val) { 208 message = val; 209 return this; 210 } 211 212 /** 213 * Specifies the minimum allowed number of detections and returns Builder object. 214 * 215 * @param val the minimum allowed number of detections. 216 * @return Builder object. 217 * @noinspection ReturnOfInnerClass 218 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 219 */ 220 public Builder minimum(int val) { 221 minimum = val; 222 return this; 223 } 224 225 /** 226 * Specifies the maximum allowed number of detections and returns Builder object. 227 * 228 * @param val the maximum allowed number of detections. 229 * @return Builder object. 230 * @noinspection ReturnOfInnerClass 231 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 232 */ 233 public Builder maximum(int val) { 234 maximum = val; 235 return this; 236 } 237 238 /** 239 * Specifies whether to ignore case when matching and returns Builder object. 240 * 241 * @param val whether to ignore case when matching. 242 * @return Builder object. 243 * @noinspection ReturnOfInnerClass, BooleanParameter 244 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 245 * @noinspectionreason BooleanParameter - check fields are boolean 246 */ 247 public Builder ignoreCase(boolean val) { 248 ignoreCase = val; 249 return this; 250 } 251 252 /** 253 * Specifies the suppressor to use and returns Builder object. 254 * 255 * @param val the suppressor to use. 256 * @return current instance 257 * @noinspection ReturnOfInnerClass 258 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 259 */ 260 public Builder suppressor(MatchSuppressor val) { 261 suppressor = val; 262 return this; 263 } 264 265 /** 266 * Returns new DetectorOptions instance. 267 * 268 * @return DetectorOptions instance. 269 */ 270 public DetectorOptions build() { 271 message = Optional.ofNullable(message).orElse(""); 272 suppressor = Optional.ofNullable(suppressor).orElse(NeverSuppress.INSTANCE); 273 pattern = Optional.ofNullable(format).map(this::createPattern).orElse(null); 274 275 reportGroup = Math.max(0, reportGroup); 276 277 return DetectorOptions.this; 278 } 279 280 /** 281 * Creates pattern to use by DetectorOptions instance. 282 * 283 * @param formatValue the format to use. 284 * @return Pattern object. 285 */ 286 private Pattern createPattern(String formatValue) { 287 int options = compileFlags; 288 if (ignoreCase) { 289 options |= Pattern.CASE_INSENSITIVE; 290 } 291 return Pattern.compile(formatValue, options); 292 } 293 294 } 295 296}