001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2024 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 056 /** Default constructor.*/ 057 private DetectorOptions() { 058 } 059 060 /** 061 * Returns new Builder object. 062 * 063 * @return Builder object. 064 */ 065 public static Builder newBuilder() { 066 return new DetectorOptions().new Builder(); 067 } 068 069 /** 070 * Format of the regular expression. 071 * 072 * @return format of the regular expression. 073 */ 074 public String getFormat() { 075 return format; 076 } 077 078 /** 079 * The violation reporter to use. 080 * 081 * @return the violation reporter to use. 082 */ 083 public AbstractViolationReporter getReporter() { 084 return reporter; 085 } 086 087 /** 088 * The message to report violations with. 089 * 090 * @return the message to report violations with. 091 */ 092 public String getMessage() { 093 return message; 094 } 095 096 /** 097 * The minimum number of allowed detections. 098 * 099 * @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 /** 136 * Specifies the violation reporter and returns Builder object. 137 * 138 * @param val for reporting violations. 139 * @return Builder object. 140 * @noinspection ReturnOfInnerClass 141 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 142 */ 143 public Builder reporter(AbstractViolationReporter val) { 144 reporter = val; 145 return this; 146 } 147 148 /** 149 * Specifies the compile-flags to compile a regular expression with 150 * and returns Builder object. 151 * 152 * @param val the format to use when matching lines. 153 * @return Builder object. 154 * @noinspection ReturnOfInnerClass 155 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 156 */ 157 public Builder compileFlags(int val) { 158 compileFlags = val; 159 return this; 160 } 161 162 /** 163 * Specifies the format to use when matching lines and returns Builder object. 164 * 165 * @param val the format to use when matching lines. 166 * @return Builder object. 167 * @noinspection ReturnOfInnerClass 168 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 169 */ 170 public Builder format(String val) { 171 format = val; 172 return this; 173 } 174 175 /** 176 * Specifies message to use when reporting a match and returns Builder object. 177 * 178 * @param val message to use when reporting a match. 179 * @return Builder object. 180 * @noinspection ReturnOfInnerClass 181 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 182 */ 183 public Builder message(String val) { 184 message = val; 185 return this; 186 } 187 188 /** 189 * Specifies the minimum allowed number of detections and returns Builder object. 190 * 191 * @param val the minimum allowed number of detections. 192 * @return Builder object. 193 * @noinspection ReturnOfInnerClass 194 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 195 */ 196 public Builder minimum(int val) { 197 minimum = val; 198 return this; 199 } 200 201 /** 202 * Specifies the maximum allowed number of detections and returns Builder object. 203 * 204 * @param val the maximum allowed number of detections. 205 * @return Builder object. 206 * @noinspection ReturnOfInnerClass 207 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 208 */ 209 public Builder maximum(int val) { 210 maximum = val; 211 return this; 212 } 213 214 /** 215 * Specifies whether to ignore case when matching and returns Builder object. 216 * 217 * @param val whether to ignore case when matching. 218 * @return Builder object. 219 * @noinspection ReturnOfInnerClass, BooleanParameter 220 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 221 * @noinspectionreason BooleanParameter - check fields are boolean 222 */ 223 public Builder ignoreCase(boolean val) { 224 ignoreCase = val; 225 return this; 226 } 227 228 /** 229 * Specifies the suppressor to use and returns Builder object. 230 * 231 * @param val the suppressor to use. 232 * @return current instance 233 * @noinspection ReturnOfInnerClass 234 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class 235 */ 236 public Builder suppressor(MatchSuppressor val) { 237 suppressor = val; 238 return this; 239 } 240 241 /** 242 * Returns new DetectorOptions instance. 243 * 244 * @return DetectorOptions instance. 245 */ 246 public DetectorOptions build() { 247 message = Optional.ofNullable(message).orElse(""); 248 suppressor = Optional.ofNullable(suppressor).orElse(NeverSuppress.INSTANCE); 249 pattern = Optional.ofNullable(format).map(this::createPattern).orElse(null); 250 return DetectorOptions.this; 251 } 252 253 /** 254 * Creates pattern to use by DetectorOptions instance. 255 * 256 * @param formatValue the format to use. 257 * @return Pattern object. 258 */ 259 private Pattern createPattern(String formatValue) { 260 int options = compileFlags; 261 if (ignoreCase) { 262 options |= Pattern.CASE_INSENSITIVE; 263 } 264 return Pattern.compile(formatValue, options); 265 } 266 267 } 268 269}