Support for the CatchBlock option. The code is a bit ugly, but it works.
This commit is contained in:
parent
39a7271a2a
commit
615219883b
|
|
@ -0,0 +1,87 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// checkstyle: Checks Java source code for adherence to a set of rules.
|
||||
// Copyright (C) 2001-2002 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;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Represents the options for a catch block.
|
||||
*
|
||||
* @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a>
|
||||
*/
|
||||
public final class CatchBlockOption implements Serializable
|
||||
{
|
||||
/** maps from a string representation to an option **/
|
||||
private static final Map STR_TO_OPT = new HashMap();
|
||||
|
||||
/** represents ignoring catch blocks **/
|
||||
public static final CatchBlockOption IGNORE =
|
||||
new CatchBlockOption("ignore");
|
||||
/** represents requiring some text in the catch block **/
|
||||
public static final CatchBlockOption TEXT = new CatchBlockOption("text");
|
||||
/** represents requiring a statement in the catch block **/
|
||||
public static final CatchBlockOption STMT = new CatchBlockOption("stmt");
|
||||
|
||||
/** the string representation of the option **/
|
||||
private final String mStrRep;
|
||||
|
||||
/**
|
||||
* Creates a new <code>CatchBlockOption</code> instance.
|
||||
* @param aStrRep the string representation
|
||||
*/
|
||||
private CatchBlockOption(String aStrRep)
|
||||
{
|
||||
mStrRep = aStrRep.trim().toLowerCase();
|
||||
STR_TO_OPT.put(mStrRep, this);
|
||||
}
|
||||
|
||||
/** @see Object **/
|
||||
public String toString()
|
||||
{
|
||||
return mStrRep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the CatchBlockOption specified by a string representation. If no
|
||||
* option exists then null is returned.
|
||||
* @param aStrRep the String representation to parse
|
||||
* @return the <code>CatchBlockOption</code> value represented by aStrRep,
|
||||
* or null if none exists.
|
||||
*/
|
||||
public static CatchBlockOption decode(String aStrRep)
|
||||
{
|
||||
return (CatchBlockOption) STR_TO_OPT.get(aStrRep.trim().toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that we don't get multiple instances of one CatchBlockOption
|
||||
* during deserialization. See Section 3.6 of the Java Object
|
||||
* Serialization Specification for details.
|
||||
*
|
||||
* @return the serialization replacement object
|
||||
* @throws ObjectStreamException if a deserialization error occurs
|
||||
*/
|
||||
private Object readResolve() throws ObjectStreamException
|
||||
{
|
||||
return decode(mStrRep);
|
||||
}
|
||||
}
|
||||
|
|
@ -645,6 +645,18 @@ public class CheckStyleTask
|
|||
});
|
||||
}
|
||||
|
||||
/** @param aTo the catch block option **/
|
||||
public void setCatchBlock(final String aTo)
|
||||
{
|
||||
mOptionMemory.add(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
mConfig.setCatchBlock(extractCatchBlockOption(aTo));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** @param aTo the parenthesis padding option **/
|
||||
public void setParenPad(final String aTo)
|
||||
{
|
||||
|
|
@ -657,18 +669,6 @@ public class CheckStyleTask
|
|||
});
|
||||
}
|
||||
|
||||
/** @param aAllowed whether empty catch blocks are allowed **/
|
||||
public void setAllowEmptyCatch(final boolean aAllowed)
|
||||
{
|
||||
mOptionMemory.add(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
mConfig.setAllowEmptyCatch(aAllowed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// The doers
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -914,6 +914,22 @@ public class CheckStyleTask
|
|||
return opt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aFrom String to decode the option from
|
||||
* @return the CatchBlockOption represented by aFrom
|
||||
* @throws BuildException if unable to decode aFrom
|
||||
*/
|
||||
private CatchBlockOption extractCatchBlockOption(String aFrom)
|
||||
throws BuildException
|
||||
{
|
||||
final CatchBlockOption opt = CatchBlockOption.decode(aFrom);
|
||||
if (opt == null) {
|
||||
throw new BuildException("Unable to parse '" + aFrom + "'.",
|
||||
location);
|
||||
}
|
||||
return opt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aFrom String to decode the option from
|
||||
* @return the PadOption represented by aFrom
|
||||
|
|
|
|||
|
|
@ -186,13 +186,12 @@ public class Configuration
|
|||
private LeftCurlyOption mLCurlyOther = LeftCurlyOption.EOL;
|
||||
/** where to place right curlies **/
|
||||
private RightCurlyOption mRCurly = RightCurlyOption.SAME;
|
||||
/** how to process catch blocks **/
|
||||
private CatchBlockOption mCatchBlock = CatchBlockOption.TEXT;
|
||||
|
||||
/** how to pad parenthesis **/
|
||||
private PadOption mParenPadOption = PadOption.NOSPACE;
|
||||
|
||||
/** whether to allow emtpy exception handlers **/
|
||||
private boolean mAllowEmptyCatch = false;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Constructors
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -285,12 +284,13 @@ public class Configuration
|
|||
LeftCurlyOption.EOL, aLog));
|
||||
setRCurly(getRightCurlyOptionProperty(
|
||||
aProps, RCURLY_PROP, RightCurlyOption.SAME, aLog));
|
||||
setCatchBlock(
|
||||
getCatchBlockOptionProperty(
|
||||
aProps, CATCH_BLOCK_PROP, CatchBlockOption.TEXT, aLog));
|
||||
setParenPadOption(getPadOptionProperty(aProps,
|
||||
PAREN_PAD_PROP,
|
||||
PadOption.NOSPACE,
|
||||
aLog));
|
||||
setAllowEmptyCatch(getBooleanProperty(
|
||||
aProps, ALLOW_EMPTY_CATCH_PROP, mAllowEmptyCatch));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1005,6 +1005,18 @@ public class Configuration
|
|||
mRCurly = aTo;
|
||||
}
|
||||
|
||||
/** @return the catch block option **/
|
||||
public CatchBlockOption getCatchBlock()
|
||||
{
|
||||
return mCatchBlock;
|
||||
}
|
||||
|
||||
/** @param aTo set the catch block option **/
|
||||
public void setCatchBlock(CatchBlockOption aTo)
|
||||
{
|
||||
mCatchBlock = aTo;
|
||||
}
|
||||
|
||||
/** @return the parenthesis padding option **/
|
||||
public PadOption getParenPadOption()
|
||||
{
|
||||
|
|
@ -1017,18 +1029,6 @@ public class Configuration
|
|||
mParenPadOption = aTo;
|
||||
}
|
||||
|
||||
/** @return whether empty catch blocks are allowed */
|
||||
public boolean isAllowEmptyCatch()
|
||||
{
|
||||
return mAllowEmptyCatch;
|
||||
}
|
||||
|
||||
/** @param aAllowEmptyCatch whether empty catch blocks are allowed */
|
||||
public void setAllowEmptyCatch(boolean aAllowEmptyCatch)
|
||||
{
|
||||
mAllowEmptyCatch = aAllowEmptyCatch;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1137,6 +1137,34 @@ public class Configuration
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aProps the properties set to use
|
||||
* @param aLog where to log errors to
|
||||
* @param aName the name of the property to parse
|
||||
* @param aDefault the default value to use.
|
||||
*
|
||||
* @return the value of a CatchBlockOption property. If the property is not
|
||||
* defined or cannot be decoded, then a default value is returned.
|
||||
*/
|
||||
private static CatchBlockOption getCatchBlockOptionProperty(
|
||||
Properties aProps,
|
||||
String aName,
|
||||
CatchBlockOption aDefault,
|
||||
PrintStream aLog)
|
||||
{
|
||||
CatchBlockOption retVal = aDefault;
|
||||
final String strRep = aProps.getProperty(aName);
|
||||
if (strRep != null) {
|
||||
retVal = CatchBlockOption.decode(strRep);
|
||||
if (retVal == null) {
|
||||
aLog.println("Unable to parse " + aName +
|
||||
" property with value " + strRep +
|
||||
", defaulting to " + aDefault + ".");
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aProps the properties set to use
|
||||
* @param aLog where to log errors to
|
||||
|
|
|
|||
|
|
@ -101,6 +101,6 @@ public interface Defn
|
|||
/** property name for padding around parenthesis **/
|
||||
String PAREN_PAD_PROP = "checkstyle.paren.pad";
|
||||
|
||||
/** property name for allowing empty exception handlers **/
|
||||
String ALLOW_EMPTY_CATCH_PROP = "checkstyle.allow.empty.catch";
|
||||
/** property name for catch block options **/
|
||||
String CATCH_BLOCK_PROP = "checkstyle.catchblock";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ class Verifier
|
|||
{
|
||||
log(aSig.getName().getLineNo(),
|
||||
aSig.getName().getColumnNo(),
|
||||
"method name '" + aSig.getName() +
|
||||
"method name '" + aSig.getName().getText() +
|
||||
"' must match pattern '" + mConfig.getMethodPat() + "'.");
|
||||
}
|
||||
|
||||
|
|
@ -869,15 +869,59 @@ class Verifier
|
|||
}
|
||||
|
||||
/**
|
||||
* Report that the parser has found a (potentially empty) catch block.
|
||||
* @param aLineNo the line number of the catch keyword
|
||||
* @param aColNo the column number of the catch keyword
|
||||
* @param aIsEmpty whether the block contains any statement
|
||||
* Report that the parser has found a catch block.
|
||||
* @param aBraces the start and end braces from the catch block
|
||||
* @param aNoStmt whether there are any statements in the block
|
||||
*/
|
||||
void reportCatchBlock(int aLineNo, int aColNo, boolean aIsEmpty)
|
||||
void reportCatchBlock(MyCommonAST[] aBraces, boolean aNoStmt)
|
||||
{
|
||||
if (aIsEmpty && !mConfig.isAllowEmptyCatch()) {
|
||||
log(aLineNo, aColNo - 1, "Empty catch block.");
|
||||
if (aNoStmt && (mConfig.getCatchBlock() == CatchBlockOption.STMT)) {
|
||||
log(aBraces[0].getLineNo(),
|
||||
aBraces[0].getColumnNo(),
|
||||
"Must have at least one statement.");
|
||||
}
|
||||
else if (mConfig.getCatchBlock() == CatchBlockOption.TEXT) {
|
||||
if (aBraces[0].getLineNo() == aBraces[1].getLineNo()) {
|
||||
// Handle braces on the same line
|
||||
final String txt = mLines[aBraces[0].getLineNo() - 1]
|
||||
.substring(aBraces[0].getColumnNo() + 1,
|
||||
aBraces[1].getColumnNo());
|
||||
if (txt.trim().length() == 0) {
|
||||
log(aBraces[0].getLineNo(),
|
||||
aBraces[0].getColumnNo(),
|
||||
"Empty catch block.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// check only whitespace of first & last lines
|
||||
if ((mLines[aBraces[0].getLineNo() - 1]
|
||||
.substring(aBraces[0].getColumnNo() + 1).trim().length()
|
||||
== 0)
|
||||
&&
|
||||
(mLines[aBraces[1].getLineNo() - 1]
|
||||
.substring(0, aBraces[1].getColumnNo()).trim().length()
|
||||
== 0))
|
||||
{
|
||||
|
||||
// Need to check if all lines are also only whitespace
|
||||
boolean isBlank = true;
|
||||
for (int i = aBraces[0].getLineNo();
|
||||
i < (aBraces[1].getLineNo() - 1);
|
||||
i++)
|
||||
{
|
||||
if (mLines[i].trim().length() > 0) {
|
||||
isBlank = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isBlank) {
|
||||
log(aBraces[0].getLineNo(),
|
||||
aBraces[0].getColumnNo(),
|
||||
"Empty catch block.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -754,7 +754,7 @@ tryBlock
|
|||
{
|
||||
ver.verifyWSAroundBegin(
|
||||
c.getLine(), c.getColumn(), c.getText());
|
||||
ver.reportCatchBlock(c.getLine(), c.getColumn(), isEmpty[0]);
|
||||
ver.reportCatchBlock(stmtBraces, isEmpty[0]);
|
||||
ver.verifyLCurlyOther(c.getLine(), stmtBraces[0]);
|
||||
}
|
||||
)*
|
||||
|
|
|
|||
Loading…
Reference in New Issue