All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.puppycrawl.tools.checkstyle.checks.regexp.RegexpMultilineCheck Maven / Gradle / Ivy

Go to download

Checkstyle is a development tool to help programmers write Java code that adheres to a coding standard

There is a newer version: 10.18.1
Show newest version
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2021 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle.checks.regexp;

import java.io.File;
import java.util.regex.Pattern;

import com.puppycrawl.tools.checkstyle.StatelessCheck;
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
import com.puppycrawl.tools.checkstyle.api.FileText;

/**
 * 

* Checks that a specified pattern matches across multiple lines in any file type. *

*

* Rationale: This check can be used to when the regular expression can be span multiple lines. *

*
    *
  • * Property {@code format} - Specify the format of the regular expression to match. * Type is {@code java.lang.String}. * Default value is {@code "$."}. *
  • *
  • * Property {@code message} - Specify the message which is used to notify about * violations, if empty then default (hard-coded) message is used. * Type is {@code java.lang.String}. * Default value is {@code null}. *
  • *
  • * Property {@code ignoreCase} - Control whether to ignore case when searching. * Type is {@code boolean}. * Default value is {@code false}. *
  • *
  • * Property {@code minimum} - Specify the minimum number of matches required in each file. * Type is {@code int}. * Default value is {@code 0}. *
  • *
  • * Property {@code maximum} - Specify the maximum number of matches required in each file. * Type is {@code int}. * Default value is {@code 0}. *
  • *
  • * Property {@code matchAcrossLines} - Control whether to match expressions * across multiple lines. * Type is {@code boolean}. * Default value is {@code false}. *
  • *
  • * Property {@code fileExtensions} - Specify the file type extension of files to process. * Type is {@code java.lang.String[]}. * Default value is {@code ""}. *
  • *
*

* To run the check with its default configuration (no matches will be): *

*
 * <module name="RegexpMultiline"/>
 * 
*

Example:

*
 * void method() {
 *   int i = 5; // OK
 *   System.out.println(i); // OK
 * }
 * 
*

* To configure the check to find calls to print to the console: *

*
 * <module name="RegexpMultiline">
 *   <property name="format" value="System\.(out)|(err)\.print(ln)?\("/>
 * </module>
 * 
*

* Example: *

*
 * void method() {
 *   System.out.print("Example");   // violation
 *   System.err.println("Example"); // violation
 *   System.out.print
 *     ("Example");                 // violation
 *   System.err.println
 *     ("Example");          // OK
 *   System
 *   .out.print("Example");  // OK
 *   System
 *   .err.println("Example");       // violation
 *   System.
 *   out.print("Example");   // OK
 *   System.
 *   err.println("Example");        // violation
 * }
 * 
*

* To configure the check to match text that spans multiple lines, * like normal code in a Java file: *

*
 * <module name="RegexpMultiline">
 *   <property name="matchAcrossLines" value="true"/>
 *   <property name="format" value="System\.out.*?print\("/>
 * </module>
 * 
*

* Example: *

*
 * void method() {
 *   System.out.print("Example");  // violation
 *   System.err.println("Example");
 *   System.out.print              // violation
 *     ("Example");
 *   System.err.println
 *     ("Example");
 *   System
 *   .out.print("Example");
 *   System
 *   .err.println("Example");
 *   System.
 *   out.print("Example");
 *   System.
 *   err.println("Example");
 * }
 * 
*

* Note: Beware of the greedy regular expression used in the above example. * {@code .*} will match as much as possible and not produce multiple violations * in the file if multiple groups of lines could match the expression. To prevent * an expression being too greedy, avoid overusing matching all text or allow it * to be optional, like {@code .*?}. Changing the example expression to not be * greedy will allow multiple violations in the example to be found in the same file. *

*

* To configure the check to match a maximum of three test strings: *

*
 * <module name="RegexpMultiline">
 *   <property name="format" value="Test #[0-9]+:[A-Za-z ]+"/>
 *   <property name="ignoreCase" value="true"/>
 *   <property name="maximum" value="3"/>
 * </module>
 * 
*

* Example: *

*
 * void method() {
 *   System.out.println("Test #1: this is a test string"); // OK
 *   System.out.println("TeSt #2: This is a test string"); // OK
 *   System.out.println("TEST #3: This is a test string"); // OK
 *   int i = 5;
 *   System.out.println("Value of i: " + i);
 *   System.out.println("Test #4: This is a test string"); // violation
 *   System.out.println("TEst #5: This is a test string"); // violation
 * }
 * 
*

* To configure the check to match a minimum of two test strings: *

*
 * <module name="RegexpMultiline">
 *   <property name="format" value="Test #[0-9]+:[A-Za-z ]+"/>
 *   <property name="minimum" value="2"/>
 * </module>
 * 
*

* Example: *

*
 * void method() {
 *   System.out.println("Test #1: this is a test string"); // violation
 *   System.out.println("TEST #2: This is a test string"); // OK, "ignoreCase" is false by default
 *   int i = 5;
 *   System.out.println("Value of i: " + i);
 *   System.out.println("Test #3: This is a test string"); // violation
 *   System.out.println("Test #4: This is a test string"); // violation
 * }
 * 
*

* To configure the check to restrict an empty file: *

*
 * <module name="RegexpMultiline">
 *     <property name="format" value="^\s*$" />
 *     <property name="matchAcrossLines" value="true" />
 *     <property name="message" value="Empty file is not allowed" />
 * </module>
 * 
*

* Example of violation from the above config: *

*
 * /var/tmp$ cat -n Test.java
 * 1
 * 2
 * 3
 * 4
 * 
*

Result:

*
 * /var/tmp/Test.java // violation, a file must not be empty.
 * 
*

* Parent is {@code com.puppycrawl.tools.checkstyle.Checker} *

*

* Violation Message Keys: *

*
    *
  • * {@code regexp.StackOverflowError} *
  • *
  • * {@code regexp.empty} *
  • *
  • * {@code regexp.exceeded} *
  • *
  • * {@code regexp.minimum} *
  • *
* * @since 5.0 */ @StatelessCheck public class RegexpMultilineCheck extends AbstractFileSetCheck { /** Specify the format of the regular expression to match. */ private String format = "$."; /** * Specify the message which is used to notify about violations, * if empty then default (hard-coded) message is used. */ private String message; /** Specify the minimum number of matches required in each file. */ private int minimum; /** Specify the maximum number of matches required in each file. */ private int maximum; /** Control whether to ignore case when searching. */ private boolean ignoreCase; /** Control whether to match expressions across multiple lines. */ private boolean matchAcrossLines; /** The detector to use. */ private MultilineDetector detector; @Override public void beginProcessing(String charset) { final DetectorOptions options = DetectorOptions.newBuilder() .reporter(this) .compileFlags(getRegexCompileFlags()) .format(format) .message(message) .minimum(minimum) .maximum(maximum) .ignoreCase(ignoreCase) .build(); detector = new MultilineDetector(options); } @Override protected void processFiltered(File file, FileText fileText) { detector.processLines(fileText); } /** * Retrieves the compile flags for the regular expression being built based * on {@code matchAcrossLines}. * * @return The compile flags. */ private int getRegexCompileFlags() { final int result; if (matchAcrossLines) { result = Pattern.DOTALL; } else { result = Pattern.MULTILINE; } return result; } /** * Setter to specify the format of the regular expression to match. * * @param format the format of the regular expression to match. */ public void setFormat(String format) { this.format = format; } /** * Setter to specify the message which is used to notify about violations, * if empty then default (hard-coded) message is used. * * @param message the message to report for a match. */ public void setMessage(String message) { this.message = message; } /** * Setter to specify the minimum number of matches required in each file. * * @param minimum the minimum number of matches required in each file. */ public void setMinimum(int minimum) { this.minimum = minimum; } /** * Setter to specify the maximum number of matches required in each file. * * @param maximum the maximum number of matches required in each file. */ public void setMaximum(int maximum) { this.maximum = maximum; } /** * Setter to control whether to ignore case when searching. * * @param ignoreCase whether to ignore case when searching. */ public void setIgnoreCase(boolean ignoreCase) { this.ignoreCase = ignoreCase; } /** * Setter to control whether to match expressions across multiple lines. * * @param matchAcrossLines whether to match expressions across multiple lines. */ public void setMatchAcrossLines(boolean matchAcrossLines) { this.matchAcrossLines = matchAcrossLines; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy