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 com.puppycrawl.tools.checkstyle.PropertyType; 023import com.puppycrawl.tools.checkstyle.StatelessCheck; 024import com.puppycrawl.tools.checkstyle.XdocsPropertyType; 025import com.puppycrawl.tools.checkstyle.api.AbstractCheck; 026import com.puppycrawl.tools.checkstyle.api.DetailAST; 027import com.puppycrawl.tools.checkstyle.utils.CommonUtil; 028 029/** 030 * <p> 031 * Checks that a specified pattern matches a single-line in Java files. 032 * </p> 033 * <p> 034 * This class is variation on 035 * <a href="https://checkstyle.org/checks/regexp/regexpsingleline.html#RegexpSingleline"> 036 * RegexpSingleline</a> 037 * for detecting single-lines that match a supplied regular expression in Java files. 038 * It supports suppressing matches in Java comments. 039 * </p> 040 * <ul> 041 * <li> 042 * Property {@code format} - Specify the format of the regular expression to match. 043 * Type is {@code java.util.regex.Pattern}. 044 * Default value is {@code "$."}. 045 * </li> 046 * <li> 047 * Property {@code ignoreCase} - Control whether to ignore case when searching. 048 * Type is {@code boolean}. 049 * Default value is {@code false}. 050 * </li> 051 * <li> 052 * Property {@code ignoreComments} - Control whether to ignore text in comments when searching. 053 * Type is {@code boolean}. 054 * Default value is {@code false}. 055 * </li> 056 * <li> 057 * Property {@code maximum} - Specify the maximum number of matches required in each file. 058 * Type is {@code int}. 059 * Default value is {@code 0}. 060 * </li> 061 * <li> 062 * Property {@code message} - Specify the message which is used to notify about 063 * violations, if empty then default (hard-coded) message is used. 064 * Type is {@code java.lang.String}. 065 * Default value is {@code null}. 066 * </li> 067 * <li> 068 * Property {@code minimum} - Specify the minimum number of matches required in each file. 069 * Type is {@code int}. 070 * Default value is {@code 0}. 071 * </li> 072 * </ul> 073 * <p> 074 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} 075 * </p> 076 * <p> 077 * Violation Message Keys: 078 * </p> 079 * <ul> 080 * <li> 081 * {@code regexp.exceeded} 082 * </li> 083 * <li> 084 * {@code regexp.minimum} 085 * </li> 086 * </ul> 087 * 088 * @since 6.0 089 */ 090@StatelessCheck 091public class RegexpSinglelineJavaCheck extends AbstractCheck { 092 093 /** Specify the format of the regular expression to match. */ 094 @XdocsPropertyType(PropertyType.PATTERN) 095 private String format = "$."; 096 /** 097 * Specify the message which is used to notify about violations, 098 * if empty then default (hard-coded) message is used. 099 */ 100 private String message; 101 /** Specify the minimum number of matches required in each file. */ 102 private int minimum; 103 /** Specify the maximum number of matches required in each file. */ 104 private int maximum; 105 /** Control whether to ignore case when searching. */ 106 private boolean ignoreCase; 107 /** Control whether to ignore text in comments when searching. */ 108 private boolean ignoreComments; 109 110 @Override 111 public int[] getDefaultTokens() { 112 return getRequiredTokens(); 113 } 114 115 @Override 116 public int[] getAcceptableTokens() { 117 return getRequiredTokens(); 118 } 119 120 @Override 121 public int[] getRequiredTokens() { 122 return CommonUtil.EMPTY_INT_ARRAY; 123 } 124 125 // suppress deprecation until https://github.com/checkstyle/checkstyle/issues/11166 126 @SuppressWarnings("deprecation") 127 @Override 128 public void beginTree(DetailAST rootAST) { 129 MatchSuppressor suppressor = null; 130 if (ignoreComments) { 131 suppressor = new CommentSuppressor(getFileContents()); 132 } 133 134 final DetectorOptions options = DetectorOptions.newBuilder() 135 .reporter(this) 136 .suppressor(suppressor) 137 .format(format) 138 .message(message) 139 .minimum(minimum) 140 .maximum(maximum) 141 .ignoreCase(ignoreCase) 142 .build(); 143 final SinglelineDetector detector = new SinglelineDetector(options); 144 detector.processLines(getFileContents().getText()); 145 } 146 147 /** 148 * Setter to specify the format of the regular expression to match. 149 * 150 * @param format the format of the regular expression to match. 151 * @since 5.0 152 */ 153 public void setFormat(String format) { 154 this.format = format; 155 } 156 157 /** 158 * Setter to specify the message which is used to notify about violations, 159 * if empty then default (hard-coded) message is used. 160 * 161 * @param message the message to report for a match. 162 * @since 6.0 163 */ 164 public void setMessage(String message) { 165 this.message = message; 166 } 167 168 /** 169 * Setter to specify the minimum number of matches required in each file. 170 * 171 * @param minimum the minimum number of matches required in each file. 172 * @since 5.0 173 */ 174 public void setMinimum(int minimum) { 175 this.minimum = minimum; 176 } 177 178 /** 179 * Setter to specify the maximum number of matches required in each file. 180 * 181 * @param maximum the maximum number of matches required in each file. 182 * @since 5.0 183 */ 184 public void setMaximum(int maximum) { 185 this.maximum = maximum; 186 } 187 188 /** 189 * Setter to control whether to ignore case when searching. 190 * 191 * @param ignoreCase whether to ignore case when searching. 192 * @since 5.0 193 */ 194 public void setIgnoreCase(boolean ignoreCase) { 195 this.ignoreCase = ignoreCase; 196 } 197 198 /** 199 * Setter to control whether to ignore text in comments when searching. 200 * 201 * @param ignore whether to ignore text in comments when searching. 202 * @since 5.0 203 */ 204 public void setIgnoreComments(boolean ignore) { 205 ignoreComments = ignore; 206 } 207 208}