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 java.io.File; 023 024import com.puppycrawl.tools.checkstyle.StatelessCheck; 025import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck; 026import com.puppycrawl.tools.checkstyle.api.FileText; 027 028/** 029 * <p> 030 * A check for detecting single lines that match a supplied regular expression. 031 * Works with any file type. 032 * </p> 033 * <p> 034 * Rationale: This check can be used to prototype checks and to find common bad 035 * practice such as calling {@code ex.printStacktrace()}, 036 * {@code System.out.println()}, {@code System.exit()}, etc. 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 fileExtensions} - Specify the file type extension of files to process. 062 * Default value is {@code all files}. 063 * </li> 064 * </ul> 065 * <p> 066 * To configure the check to find trailing whitespace at the end of a line: 067 * </p> 068 * <pre> 069 * <module name="RegexpSingleline"> 070 * <!-- \s matches whitespace character, $ matches end of line. --> 071 * <property name="format" value="\s+$"/> 072 * </module> 073 * </pre> 074 * <p> 075 * To configure the check to find trailing whitespace at the end of a line, 076 * with some <i>slack</i> of allowing two occurrences per file: 077 * </p> 078 * <pre> 079 * <module name="RegexpSingleline"> 080 * <property name="format" value="\s+$"/> 081 * <!-- next line not required as 0 is the default --> 082 * <property name="minimum" value="0"/> 083 * <property name="maximum" value="2"/> 084 * </module> 085 * </pre> 086 * <p> 087 * An example of how to configure the check to make sure a copyright statement 088 * is included in the file: 089 * </p> 090 * <pre> 091 * <module name="RegexpSingleline"> 092 * <property name="format" value="This file is copyrighted"/> 093 * <property name="minimum" value="1"/> 094 * <!-- Need to specify a maximum, so 10 times is more than enough. --> 095 * <property name="maximum" value="10"/> 096 * </module> 097 * </pre> 098 * 099 * @since 5.0 100 */ 101@StatelessCheck 102public class RegexpSinglelineCheck extends AbstractFileSetCheck { 103 104 /** Specify the format of the regular expression to match. */ 105 private String format = "$."; 106 /** 107 * Specify the message which is used to notify about violations, 108 * if empty then default (hard-coded) message is used. 109 */ 110 private String message; 111 /** Specify the minimum number of matches required in each file. */ 112 private int minimum; 113 /** Specify the maximum number of matches required in each file. */ 114 private int maximum; 115 /** Control whether to ignore case when searching. */ 116 private boolean ignoreCase; 117 118 /** The detector to use. */ 119 private SinglelineDetector detector; 120 121 @Override 122 public void beginProcessing(String charset) { 123 final DetectorOptions options = DetectorOptions.newBuilder() 124 .reporter(this) 125 .compileFlags(0) 126 .format(format) 127 .message(message) 128 .minimum(minimum) 129 .maximum(maximum) 130 .ignoreCase(ignoreCase) 131 .build(); 132 detector = new SinglelineDetector(options); 133 } 134 135 @Override 136 protected void processFiltered(File file, FileText fileText) { 137 detector.processLines(fileText); 138 } 139 140 /** 141 * Setter to specify the format of the regular expression to match. 142 * 143 * @param format the format of the regular expression to match. 144 */ 145 public void setFormat(String format) { 146 this.format = format; 147 } 148 149 /** 150 * Setter to specify the message which is used to notify about violations, 151 * if empty then default (hard-coded) message is used. 152 * 153 * @param message the message to report for a match. 154 */ 155 public void setMessage(String message) { 156 this.message = message; 157 } 158 159 /** 160 * Setter to specify the minimum number of matches required in each file. 161 * 162 * @param minimum the minimum number of matches required in each file. 163 */ 164 public void setMinimum(int minimum) { 165 this.minimum = minimum; 166 } 167 168 /** 169 * Setter to specify the maximum number of matches required in each file. 170 * 171 * @param maximum the maximum number of matches required in each file. 172 */ 173 public void setMaximum(int maximum) { 174 this.maximum = maximum; 175 } 176 177 /** 178 * Setter to control whether to ignore case when searching. 179 * 180 * @param ignoreCase whether to ignore case when searching. 181 */ 182 public void setIgnoreCase(boolean ignoreCase) { 183 this.ignoreCase = ignoreCase; 184 } 185 186}