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.io.File;
023
024import com.puppycrawl.tools.checkstyle.PropertyType;
025import com.puppycrawl.tools.checkstyle.StatelessCheck;
026import com.puppycrawl.tools.checkstyle.XdocsPropertyType;
027import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
028import com.puppycrawl.tools.checkstyle.api.FileText;
029
030/**
031 * <div>
032 * Checks that a specified pattern matches a single-line in any file type.
033 * </div>
034 *
035 * <p>
036 * Rationale: This check can be used to prototype checks and to find common bad
037 * practice such as calling {@code ex.printStacktrace()},
038 * {@code System.out.println()}, {@code System.exit()}, etc.
039 * </p>
040 * <ul>
041 * <li>
042 * Property {@code fileExtensions} - Specify the file extensions of the files to process.
043 * Type is {@code java.lang.String[]}.
044 * Default value is {@code ""}.
045 * </li>
046 * <li>
047 * Property {@code format} - Specify the format of the regular expression to match.
048 * Type is {@code java.util.regex.Pattern}.
049 * Default value is {@code "$."}.
050 * </li>
051 * <li>
052 * Property {@code ignoreCase} - Control whether to ignore case 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 *
074 * <p>
075 * Parent is {@code com.puppycrawl.tools.checkstyle.Checker}
076 * </p>
077 *
078 * <p>
079 * Violation Message Keys:
080 * </p>
081 * <ul>
082 * <li>
083 * {@code regexp.exceeded}
084 * </li>
085 * <li>
086 * {@code regexp.minimum}
087 * </li>
088 * </ul>
089 *
090 * @since 5.0
091 */
092@StatelessCheck
093public class RegexpSinglelineCheck extends AbstractFileSetCheck {
094
095    /** Specify the format of the regular expression to match. */
096    @XdocsPropertyType(PropertyType.PATTERN)
097    private String format = "$.";
098    /**
099     * Specify the message which is used to notify about violations,
100     * if empty then default (hard-coded) message is used.
101     */
102    private String message;
103    /** Specify the minimum number of matches required in each file. */
104    private int minimum;
105    /** Specify the maximum number of matches required in each file. */
106    private int maximum;
107    /** Control whether to ignore case when searching. */
108    private boolean ignoreCase;
109
110    /** The detector to use. */
111    private SinglelineDetector detector;
112
113    @Override
114    public void beginProcessing(String charset) {
115        final DetectorOptions options = DetectorOptions.newBuilder()
116            .reporter(this)
117            .format(format)
118            .message(message)
119            .minimum(minimum)
120            .maximum(maximum)
121            .ignoreCase(ignoreCase)
122            .build();
123        detector = new SinglelineDetector(options);
124    }
125
126    @Override
127    protected void processFiltered(File file, FileText fileText) {
128        detector.processLines(fileText);
129    }
130
131    /**
132     * Setter to specify the format of the regular expression to match.
133     *
134     * @param format the format of the regular expression to match.
135     * @since 5.0
136     */
137    public void setFormat(String format) {
138        this.format = format;
139    }
140
141    /**
142     * Setter to specify the message which is used to notify about violations,
143     * if empty then default (hard-coded) message is used.
144     *
145     * @param message the message to report for a match.
146     * @since 5.0
147     */
148    public void setMessage(String message) {
149        this.message = message;
150    }
151
152    /**
153     * Setter to specify the minimum number of matches required in each file.
154     *
155     * @param minimum the minimum number of matches required in each file.
156     * @since 5.0
157     */
158    public void setMinimum(int minimum) {
159        this.minimum = minimum;
160    }
161
162    /**
163     * Setter to specify the maximum number of matches required in each file.
164     *
165     * @param maximum the maximum number of matches required in each file.
166     * @since 5.0
167     */
168    public void setMaximum(int maximum) {
169        this.maximum = maximum;
170    }
171
172    /**
173     * Setter to control whether to ignore case when searching.
174     *
175     * @param ignoreCase whether to ignore case when searching.
176     * @since 5.0
177     */
178    public void setIgnoreCase(boolean ignoreCase) {
179        this.ignoreCase = ignoreCase;
180    }
181
182}