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