/projects/checkstyle-5.6/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/RegexpCheck.java
Java | 256 lines | 138 code | 27 blank | 91 comment | 23 complexity | 1ec9debe7f409f5b64c56950c78076f2 MD5 | raw file
- ////////////////////////////////////////////////////////////////////////////////
- // checkstyle: Checks Java source code for adherence to a set of rules.
- // Copyright (C) 2001-2012 Oliver Burn
- //
- // 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;
-
- import com.google.common.collect.Lists;
- import com.puppycrawl.tools.checkstyle.api.DetailAST;
- import com.puppycrawl.tools.checkstyle.api.FileContents;
- import java.util.List;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
-
- /**
- * <p>
- * A check that makes sure that a specified pattern exists (or not) in the file.
- * </p>
- * <p>
- * An example of how to configure the check to make sure a copyright statement
- * is included in the file (but without requirements on where in the file
- * it should be):
- * </p>
- * <pre>
- * <module name="RequiredRegexp">
- * <property name="format" value="This code is copyrighted"/>
- * </module>
- * </pre>
- * <p>
- * And to make sure the same statement appears at the beginning of the file.
- * </p>
- * <pre>
- * <module name="RequiredRegexp">
- * <property name="format" value="\AThis code is copyrighted"/>
- * </module>
- * </pre>
- * @author Stan Quinn
- */
- public class RegexpCheck extends AbstractFormatCheck
- {
- /** Default duplicate limit */
- private static final int DEFAULT_DUPLICATE_LIMIT = -1;
-
- /** Default error report limit */
- private static final int DEFAULT_ERROR_LIMIT = 100;
-
- /** Error count exceeded message */
- private static final String ERROR_LIMIT_EXCEEDED_MESSAGE =
- "The error limit has been exceeded, "
- + "the check is aborting, there may be more unreported errors.";
-
- /** Custom message for report. */
- private String mMessage = "";
-
- /** Ignore matches within comments? **/
- private boolean mIgnoreComments;
-
- /** Pattern illegal? */
- private boolean mIllegalPattern;
-
- /** Error report limit */
- private int mErrorLimit = DEFAULT_ERROR_LIMIT;
-
- /** Disallow more than x duplicates? */
- private int mDuplicateLimit;
-
- /** Boolean to say if we should check for duplicates. */
- private boolean mCheckForDuplicates;
-
- /** Tracks number of matches made */
- private int mMatchCount;
-
- /** Tracks number of errors */
- private int mErrorCount;
-
- /** Relates StringBuffer positions to line # and column */
- private final List<Integer[]> mCharacters = Lists.newArrayList();
-
- /** The mMatcher */
- private Matcher mMatcher;
-
- /**
- * Instantiates an new RegexpCheck.
- */
- public RegexpCheck()
- {
- super("$^", Pattern.MULTILINE); // the empty language
- }
-
- /**
- * Setter for message property.
- * @param aMessage custom message which should be used in report.
- */
- public void setMessage(String aMessage)
- {
- mMessage = (aMessage == null) ? "" : aMessage;
- }
-
- /**
- * Getter for message property.
- * I'm not sure if this gets used by anything outside,
- * I just included it because GenericIllegalRegexp had it,
- * it's being used in logMessage() so it's covered in EMMA.
- * @return custom message to be used in report.
- */
- public String getMessage()
- {
- return mMessage;
- }
-
- /**
- * Sets if matches within comments should be ignored.
- * @param aIgnoreComments True if comments should be ignored.
- */
- public void setIgnoreComments(boolean aIgnoreComments)
- {
- mIgnoreComments = aIgnoreComments;
- }
-
- /**
- * Sets if pattern is illegal, otherwise pattern is required.
- * @param aIllegalPattern True if pattern is not allowed.
- */
- public void setIllegalPattern(boolean aIllegalPattern)
- {
- mIllegalPattern = aIllegalPattern;
- }
-
- /**
- * Sets the limit on the number of errors to report.
- * @param aErrorLimit the number of errors to report.
- */
- public void setErrorLimit(int aErrorLimit)
- {
- mErrorLimit = aErrorLimit;
- }
-
- /**
- * Sets the maximum number of instances of required pattern allowed.
- * @param aDuplicateLimit negative values mean no duplicate checking,
- * any positive value is used as the limit.
- */
- public void setDuplicateLimit(int aDuplicateLimit)
- {
- mDuplicateLimit = aDuplicateLimit;
- mCheckForDuplicates = (mDuplicateLimit > DEFAULT_DUPLICATE_LIMIT);
- }
-
- @Override
- public int[] getDefaultTokens()
- {
- return new int[0];
- }
-
- @Override
- public void beginTree(DetailAST aRootAST)
- {
- mCharacters.clear();
- final Pattern pattern = getRegexp();
- final String[] lines = getLines();
- final StringBuffer sb = new StringBuffer();
- for (int i = 0; i < lines.length; i++) {
- sb.append(lines[i]);
- sb.append('\n');
- for (int j = 0; j < (lines[i].length() + 1); j++) {
- mCharacters.add(new Integer[] {i + 1, j});
- }
- }
- mMatcher = pattern.matcher(sb.toString());
- mMatchCount = 0;
- mErrorCount = 0;
- findMatch();
- }
-
- /** recursive method that finds the matches. */
- private void findMatch()
- {
- int startLine;
- int startColumn;
- int endLine;
- int endColumn;
- boolean foundMatch;
- boolean ignore = false;
-
- foundMatch = mMatcher.find();
- if (!foundMatch && !mIllegalPattern && (mMatchCount == 0)) {
- logMessage(0);
- }
- else if (foundMatch) {
- startLine = (mCharacters.get(mMatcher.start()))[0].
- intValue();
- startColumn = (mCharacters.get(mMatcher.start()))[1].
- intValue();
- endLine = (mCharacters.get(mMatcher.end() - 1))[0].
- intValue();
- endColumn = (mCharacters.get(mMatcher.end() - 1))[1].
- intValue();
- if (mIgnoreComments) {
- final FileContents theFileContents = getFileContents();
- ignore = theFileContents.hasIntersectionWithComment(startLine,
- startColumn, endLine, endColumn);
- }
- if (!ignore) {
- mMatchCount++;
- if (mIllegalPattern || (mCheckForDuplicates
- && ((mMatchCount - 1) > mDuplicateLimit)))
- {
- mErrorCount++;
- logMessage(startLine);
- }
- }
- if ((mErrorCount < mErrorLimit)
- && (ignore || mIllegalPattern || mCheckForDuplicates))
- {
- findMatch();
- }
- }
- }
-
- /**
- * Displays the right message.
- * @param aLineNumber the line number the message relates to.
- */
- private void logMessage(int aLineNumber)
- {
- String message = "".equals(getMessage()) ? getFormat() : mMessage;
- if (mErrorCount >= mErrorLimit) {
- message = ERROR_LIMIT_EXCEEDED_MESSAGE + message;
- }
- if (mIllegalPattern) {
- log(aLineNumber, "illegal.regexp", message);
- }
- else {
- if (aLineNumber > 0) {
- log(aLineNumber, "duplicate.regexp", message);
- }
- else {
- log(aLineNumber, "required.regexp", message);
- }
- }
- }
- }
-