001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2019 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.StatelessCheck; 023import com.puppycrawl.tools.checkstyle.api.AbstractCheck; 024import com.puppycrawl.tools.checkstyle.api.DetailAST; 025import com.puppycrawl.tools.checkstyle.utils.CommonUtil; 026 027/** 028 * <p> 029 * A check for detecting single lines that match a supplied 030 * regular expression in Java files. 031 * </p> 032 * <p> 033 * This class is variation on 034 * <a href="https://checkstyle.org/config_regexp.html#RegexpSingleline">RegexpSingleline</a> 035 * for detecting single lines that match a supplied regular expression in Java files. 036 * It supports suppressing matches in Java comments. 037 * </p> 038 * <ul> 039 * <li> 040 * Property {@code format} - Specify the format of the regular expression to match. 041 * Default value is {@code "$."}. 042 * </li> 043 * <li> 044 * Property {@code message} - Specify the message which is used to notify about 045 * violations, if empty then default (hard-coded) message is used. 046 * Default value is {@code null}. 047 * </li> 048 * <li> 049 * Property {@code ignoreCase} - Control whether to ignore case when searching. 050 * Default value is {@code false}. 051 * </li> 052 * <li> 053 * Property {@code minimum} - Specify the minimum number of matches required in each file. 054 * Default value is {@code 0}. 055 * </li> 056 * <li> 057 * Property {@code maximum} - Specify the maximum number of matches required in each file. 058 * Default value is {@code 0}. 059 * </li> 060 * <li> 061 * Property {@code ignoreComments} - Control whether to ignore text in comments when searching. 062 * Default value is {@code false}. 063 * </li> 064 * </ul> 065 * <p> 066 * To configure the check for calls to {@code System.out.println}, except in comments: 067 * </p> 068 * <pre> 069 * <module name="RegexpSinglelineJava"> 070 * <!-- . matches any character, so we need to 071 * escape it and use \. to match dots. --> 072 * <property name="format" value="System\.out\.println"/> 073 * <property name="ignoreComments" value="true"/> 074 * </module> 075 * </pre> 076 * <p> 077 * To configure the check to find case-insensitive occurrences of "debug": 078 * </p> 079 * <pre> 080 * <module name="RegexpSinglelineJava"> 081 * <property name="format" value="debug"/> 082 * <property name="ignoreCase" value="true"/> 083 * </module> 084 * </pre> 085 * 086 * @since 6.0 087 */ 088@StatelessCheck 089public class RegexpSinglelineJavaCheck extends AbstractCheck { 090 091 /** Specify the format of the regular expression to match. */ 092 private String format = "$."; 093 /** 094 * Specify the message which is used to notify about violations, 095 * if empty then default (hard-coded) message is used. 096 */ 097 private String message; 098 /** Specify the minimum number of matches required in each file. */ 099 private int minimum; 100 /** Specify the maximum number of matches required in each file. */ 101 private int maximum; 102 /** Control whether to ignore case when searching. */ 103 private boolean ignoreCase; 104 /** Control whether to ignore text in comments when searching. */ 105 private boolean ignoreComments; 106 107 @Override 108 public int[] getDefaultTokens() { 109 return getRequiredTokens(); 110 } 111 112 @Override 113 public int[] getAcceptableTokens() { 114 return getRequiredTokens(); 115 } 116 117 @Override 118 public int[] getRequiredTokens() { 119 return CommonUtil.EMPTY_INT_ARRAY; 120 } 121 122 @Override 123 public void beginTree(DetailAST rootAST) { 124 MatchSuppressor suppressor = null; 125 if (ignoreComments) { 126 suppressor = new CommentSuppressor(getFileContents()); 127 } 128 129 final DetectorOptions options = DetectorOptions.newBuilder() 130 .reporter(this) 131 .compileFlags(0) 132 .suppressor(suppressor) 133 .format(format) 134 .message(message) 135 .minimum(minimum) 136 .maximum(maximum) 137 .ignoreCase(ignoreCase) 138 .build(); 139 final SinglelineDetector detector = new SinglelineDetector(options); 140 detector.processLines(getFileContents().getText()); 141 } 142 143 /** 144 * Setter to specify the format of the regular expression to match. 145 * 146 * @param format the format of the regular expression to match. 147 */ 148 public void setFormat(String format) { 149 this.format = format; 150 } 151 152 /** 153 * Setter to specify the message which is used to notify about violations, 154 * if empty then default (hard-coded) message is used. 155 * 156 * @param message the message to report for a match. 157 */ 158 public void setMessage(String message) { 159 this.message = message; 160 } 161 162 /** 163 * Setter to specify the minimum number of matches required in each file. 164 * 165 * @param minimum the minimum number of matches required in each file. 166 */ 167 public void setMinimum(int minimum) { 168 this.minimum = minimum; 169 } 170 171 /** 172 * Setter to specify the maximum number of matches required in each file. 173 * 174 * @param maximum the maximum number of matches required in each file. 175 */ 176 public void setMaximum(int maximum) { 177 this.maximum = maximum; 178 } 179 180 /** 181 * Setter to control whether to ignore case when searching. 182 * 183 * @param ignoreCase whether to ignore case when searching. 184 */ 185 public void setIgnoreCase(boolean ignoreCase) { 186 this.ignoreCase = ignoreCase; 187 } 188 189 /** 190 * Setter to control whether to ignore text in comments when searching. 191 * 192 * @param ignore whether to ignore text in comments when searching. 193 */ 194 public void setIgnoreComments(boolean ignore) { 195 ignoreComments = ignore; 196 } 197 198}