Major refactor to implement the RightCurly check. Required the ANTLR grammar

to be worked to:

- Not silently eat tokens (more to be done)

- Not get the token tree out of order for try/finally
This commit is contained in:
Oliver Burn 2002-10-07 09:17:16 +00:00
parent 51941dcf24
commit b1cfd257eb
12 changed files with 207 additions and 66 deletions

View File

@ -33,6 +33,7 @@ import java.util.Properties;
import java.util.Set;
import com.puppycrawl.tools.checkstyle.api.Utils;
import com.puppycrawl.tools.checkstyle.checks.RightCurlyOption;
import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;
@ -79,8 +80,6 @@ public class Configuration
private transient ClassLoader mLoader =
Thread.currentThread().getContextClassLoader();
/** where to place right curlies **/
private RightCurlyOption mRCurly = RightCurlyOption.SAME;
/** how to pad parenthesis **/
private PadOption mParenPadOption = PadOption.NOSPACE;
/** how to wrap operators **/
@ -148,8 +147,6 @@ public class Configuration
throws RESyntaxException, FileNotFoundException, IOException
{
// Init the special properties
setRCurly(getRightCurlyOptionProperty(
aProps, Defn.RCURLY_PROP, RightCurlyOption.SAME, aLog));
setJavadocScope(
Scope.getInstance(aProps.getProperty(Defn.JAVADOC_CHECKSCOPE_PROP,
Scope.PRIVATE.getName())));
@ -267,7 +264,6 @@ public class Configuration
{
final Properties retVal = new Properties();
Utils.addObjectString(retVal, Defn.RCURLY_PROP, mRCurly.toString());
Utils.addObjectString(retVal, Defn.JAVADOC_CHECKSCOPE_PROP,
mJavadocScope.getName());
Utils.addObjectString(retVal, Defn.PAREN_PAD_PROP,
@ -576,18 +572,6 @@ public class Configuration
return getLeftCurlyOptionProperty(Defn.LCURLY_OTHER_PROP);
}
/** @return the right curly placement option **/
RightCurlyOption getRCurly()
{
return mRCurly;
}
/** @param aTo set the right curly placement option **/
private void setRCurly(RightCurlyOption aTo)
{
mRCurly = aTo;
}
/** @return the try block option **/
BlockOption getTryBlock()
{

View File

@ -87,8 +87,6 @@ public interface Defn
String LCURLY_TYPE_PROP = "checkstyle.lcurly.type";
/** property name for lcurly placement for others **/
String LCURLY_OTHER_PROP = "checkstyle.lcurly.other";
/** property name for rcurly placement **/
String RCURLY_PROP = "checkstyle.rcurly";
/** property name for padding around parenthesis **/
String PAREN_PAD_PROP = "checkstyle.paren.pad";

View File

@ -79,6 +79,7 @@ public class TreeViewer
AST r = factory.create(0,"AST ROOT");
r.setFirstChild(t);
final ASTFrame frame = new ASTFrame("Java AST", r);
frame.setSize(400, 600);
frame.setVisible(true);
frame.addWindowListener(
new WindowAdapter() {

View File

@ -34,6 +34,7 @@ import org.apache.regexp.RESyntaxException;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessages;
import com.puppycrawl.tools.checkstyle.api.Utils;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.checks.RightCurlyOption;
/**
* Verifier of Java rules. Each rule verifier takes the form of
@ -621,24 +622,6 @@ class Verifier
*/
void verifyRCurly(MyCommonAST aBrace, int aStartLine)
{
// check surrounded by whitespace
verifyWSAroundBegin(aBrace.getLineNo(),
aBrace.getColumnNo() + 1,
aBrace.getText());
// Check the actual brace
if ((mConfig.getRCurly() == RightCurlyOption.SAME)
&& (aBrace.getLineNo() != aStartLine))
{
mMessages.add(aBrace.getLineNo(), aBrace.getColumnNo(),
"line.same", "}");
}
else if ((mConfig.getRCurly() == RightCurlyOption.ALONE)
&& (aBrace.getLineNo() == aStartLine))
{
mMessages.add(aBrace.getLineNo(), aBrace.getColumnNo(),
"line.alone", "}");
}
}
/**

View File

@ -30,6 +30,7 @@ import java.io.FileReader;
import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;
import antlr.collections.AST;
/**
* Contains utility methods.
@ -172,7 +173,6 @@ public final class Utils
public static String[] getLines(String aFileName)
throws IOException
{
System.out.println("aFileName = " + aFileName);
final LineNumberReader lnr =
new LineNumberReader(new FileReader(aFileName));
final ArrayList lines = new ArrayList();
@ -186,4 +186,15 @@ public final class Utils
return (String[]) lines.toArray(new String[0]);
}
public static DetailAST getLastSibling(final AST aAST)
{
AST retVal = aAST;
AST nextSibling = retVal.getNextSibling();
while (nextSibling != null) {
retVal = nextSibling;
nextSibling = nextSibling.getNextSibling();
}
return (DetailAST) retVal;
}
}

View File

@ -0,0 +1,83 @@
////////////////////////////////////////////////////////////////////////////////
// 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.checks;
import com.puppycrawl.tools.checkstyle.JavaTokenTypes;
import com.puppycrawl.tools.checkstyle.api.Check;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.Utils;
public class RightCurlyCheck
extends Check
{
private RightCurlyOption mOption = RightCurlyOption.SAME;
/** @see com.puppycrawl.tools.checkstyle.api.Check */
public int[] getDefaultTokens()
{
return new int[] {JavaTokenTypes.LITERAL_try,
JavaTokenTypes.LITERAL_catch,
JavaTokenTypes.LITERAL_else};
}
/** @see com.puppycrawl.tools.checkstyle.api.Check */
public void visitToken(DetailAST aAST)
{
// Attempt to locate the tokens to do the check
DetailAST rcurly = null;
DetailAST nextToken = null;
if (aAST.getType() == JavaTokenTypes.LITERAL_else) {
nextToken = aAST;
rcurly = Utils.getLastSibling(
aAST.getParent().getFirstChild().getNextSibling()
.getFirstChild());
}
else if (aAST.getType() == JavaTokenTypes.LITERAL_catch) {
nextToken = (DetailAST) aAST.getNextSibling();
rcurly = Utils.getLastSibling(
aAST.getFirstChild().getNextSibling().getFirstChild());
}
else if (aAST.getType() == JavaTokenTypes.LITERAL_try) {
nextToken = (DetailAST) aAST.getFirstChild().getNextSibling();
rcurly = Utils.getLastSibling(aAST.getFirstChild().getFirstChild());
}
// If have both tokens, perform the check
if ((rcurly != null) && (nextToken != null)) {
if ((mOption == RightCurlyOption.SAME)
&& (rcurly.getLineNo() != nextToken.getLineNo()))
{
log(rcurly.getLineNo(), rcurly.getColumnNo(),
"line.same", "}");
}
else if ((mOption == RightCurlyOption.ALONE)
&& (rcurly.getLineNo() == nextToken.getLineNo()))
{
log(rcurly.getLineNo(), rcurly.getColumnNo(),
"line.alone", "}");
}
}
}
public void setOption(String aFromStr)
{
mOption = RightCurlyOption.decode(aFromStr);
}
}

View File

@ -16,7 +16,7 @@
// 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;
package com.puppycrawl.tools.checkstyle.checks;
import java.io.Serializable;
import java.io.ObjectStreamException;
@ -27,7 +27,7 @@ import java.util.HashMap;
* Represents the options for placing the right curly brace '}'.
*
* @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a>
* @version $Id: RightCurlyOption.java,v 1.4 2002-06-06 11:45:40 oburn Exp $
* @version $Id: RightCurlyOption.java,v 1.1 2002-10-07 09:17:15 oburn Exp $
*/
public final class RightCurlyOption implements Serializable
{
@ -67,7 +67,7 @@ public final class RightCurlyOption implements Serializable
return (RightCurlyOption) STR_TO_OPT.get(aStrRep.trim().toLowerCase());
}
/** @see Object **/
/** @see java.lang.Object **/
public String toString()
{
return mStrRep;
@ -79,7 +79,7 @@ public final class RightCurlyOption implements Serializable
* Serialization Specification for details.
*
* @return the serialization replacement object
* @throws ObjectStreamException if a deserialization error occurs
* @throws java.io.ObjectStreamException if a deserialization error occurs
*/
private Object readResolve() throws ObjectStreamException
{

View File

@ -31,6 +31,7 @@ public class WhitespaceAroundCheck
public int[] getDefaultTokens()
{
return new int[] {
RCURLY, // '}'
QUESTION, // '?'
COLON, // ':' TODO: dont flag after "case"
ASSIGN, // '='
@ -82,6 +83,13 @@ public class WhitespaceAroundCheck
/** @see com.puppycrawl.tools.checkstyle.api.Check */
public void visitToken(DetailAST aAST)
{
// Check for RCURLY in array initializer
if ((aAST.getType() == RCURLY)
&& (aAST.getParent().getType() == ARRAY_INIT))
{
return;
}
final String[] lines = getLines();
final String line = lines[aAST.getLineNo() - 1];
final int before = aAST.getColumnNo() - 1;

View File

@ -224,7 +224,7 @@ interfaceDefinition![DetailAST modifiers]
classBlock
: LCURLY!
( field | SEMI! )*
RCURLY!
RCURLY
{#classBlock = #([OBJBLOCK, "OBJBLOCK"], #classBlock);}
;
@ -232,7 +232,7 @@ classBlock
interfaceExtends
: (
e:"extends"!
identifier ( COMMA! identifier )*
identifier ( COMMA identifier )*
)?
{#interfaceExtends = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],
#interfaceExtends);}
@ -241,7 +241,7 @@ interfaceExtends
// A class can implement several interfaces...
implementsClause
: (
i:"implements"! identifier ( COMMA! identifier )*
i:"implements"! identifier ( COMMA identifier )*
)?
{#implementsClause = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"],
#implementsClause);}
@ -306,7 +306,7 @@ constructorBody
|
)
(statement)*
RCURLY!
RCURLY
;
explicitConstructorInvocation
@ -333,7 +333,7 @@ explicitConstructorInvocation
variableDefinitions[DetailAST mods, DetailAST t]
: variableDeclarator[(DetailAST) getASTFactory().dupTree(mods),
(DetailAST) getASTFactory().dupTree(t)]
( COMMA!
( COMMA
variableDeclarator[(DetailAST) getASTFactory().dupTree(mods),
(DetailAST) getASTFactory().dupTree(t)]
)*
@ -370,11 +370,11 @@ arrayInitializer
warnWhenFollowAmbig = false;
}
:
COMMA! initializer
COMMA initializer
)*
(COMMA!)?
(COMMA)?
)?
RCURLY!
RCURLY
;
@ -400,13 +400,13 @@ ctorHead
// This is a list of exception classes that the method is declared to throw
throwsClause
: "throws"^ identifier ( COMMA! identifier )*
: "throws"^ identifier ( COMMA identifier )*
;
// A list of formal parameters
parameterDeclarationList
: ( parameterDeclaration ( COMMA! parameterDeclaration )* )?
: ( parameterDeclaration ( COMMA parameterDeclaration )* )?
{#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"],
#parameterDeclarationList);}
;
@ -437,7 +437,7 @@ compoundStatement
: lc:LCURLY^ {#lc.setType(SLIST);}
// include the (possibly-empty) list of statements
(statement)*
RCURLY!
RCURLY
;
// This production provides a slot for adding additional statement productions.
@ -479,7 +479,7 @@ traditionalStatement
warnWhenFollowAmbig = false;
}
:
"else"! statement
elseStatement
)?
// For statement
@ -509,7 +509,7 @@ traditionalStatement
// switch/case statement
| "switch"^ LPAREN! expression RPAREN! LCURLY!
( casesGroup )*
RCURLY!
RCURLY
// exception try-catch block
| tryBlock
@ -524,6 +524,9 @@ traditionalStatement
| s:SEMI {#s.setType(EMPTY_STAT);}
;
elseStatement
: "else"^ statement
;
casesGroup
: ( // CONFLICT: to which case group do the statements bind?
@ -573,7 +576,7 @@ forIter
tryBlock
: "try"^ compoundStatement
(handler)*
( "finally"^ compoundStatement )?
( finallyHandler )?
;
@ -582,6 +585,10 @@ handler
: "catch"^ LPAREN! parameterDeclaration RPAREN! compoundStatement
;
finallyHandler
: "finally"^ compoundStatement
;
// expressions
// Note that most of these expressions follow the pattern
@ -626,7 +633,7 @@ expression
// This is a list of expressions.
expressionList
: expression (COMMA! expression)*
: expression (COMMA expression)*
{#expressionList = #(#[ELIST,"ELIST"], expressionList);}
;

View File

@ -52,7 +52,6 @@ public class CheckerTest
LeftCurlyOption.NLOW.toString());
mProps.setProperty(Defn.LCURLY_TYPE_PROP,
LeftCurlyOption.NL.toString());
mProps.setProperty(Defn.RCURLY_PROP, RightCurlyOption.ALONE.toString());
mProps.setProperty(Defn.ALLOW_NO_AUTHOR_PROP, Boolean.TRUE.toString());
mProps.setProperty(Defn.LOCALE_COUNTRY_PROP,
Locale.ENGLISH.getCountry());
@ -665,7 +664,6 @@ public class CheckerTest
throws Exception
{
mProps.setProperty(Defn.JAVADOC_CHECKSCOPE_PROP, Scope.NOTHING.getName());
mProps.setProperty(Defn.RCURLY_PROP, RightCurlyOption.SAME.toString());
final Checker c = createChecker();
final String filepath = getPath("InputLeftCurlyOther.java");
assertNotNull(c);
@ -673,13 +671,9 @@ public class CheckerTest
filepath + ":19:9: '{' should be on the previous line.",
filepath + ":21:13: '{' should be on the previous line.",
filepath + ":23:17: '{' should be on the previous line.",
filepath + ":25:17: '}' should be on the same line.",
filepath + ":28:17: '}' should be on the same line.",
filepath + ":30:17: '{' should be on the previous line.",
filepath + ":34:17: '{' should be on the previous line.",
filepath + ":40:13: '}' should be on the same line.",
filepath + ":42:13: '{' should be on the previous line.",
filepath + ":44:13: '}' should be on the same line.",
filepath + ":46:13: '{' should be on the previous line.",
filepath + ":52:9: '{' should be on the previous line.",
filepath + ":54:13: '{' should be on the previous line.",

View File

@ -4,6 +4,8 @@ import junit.framework.TestCase;
import java.util.Properties;
import com.puppycrawl.tools.checkstyle.checks.RightCurlyOption;
public class ConfigurationTest
extends TestCase
{
@ -18,20 +20,17 @@ public class ConfigurationTest
p.setProperty(Defn.MAX_LINE_LENGTH_PROP, "66");
p.setProperty(Defn.LCURLY_METHOD_PROP, "ignore");
p.setProperty(Defn.LCURLY_OTHER_PROP, "claiea");
p.setProperty(Defn.RCURLY_PROP, "ignore");
p.setProperty(Defn.CATCH_BLOCK_PROP, "text");
p.setProperty(Defn.PAREN_PAD_PROP, "ignore");
final Configuration c = new Configuration(p, System.out);
assertNotNull(c);
assertEquals(66, c.getMaxLineLength());
assertEquals(RightCurlyOption.IGNORE, c.getRCurly());
assertEquals(BlockOption.TEXT, c.getCatchBlock());
}
public void test2() throws Exception
{
final Properties p = new Properties();
p.setProperty(Defn.RCURLY_PROP, "claira");
p.setProperty(Defn.CATCH_BLOCK_PROP, "is great");
p.setProperty(Defn.PAREN_PAD_PROP, "at sleeping");
final Configuration c = new Configuration(p, System.out);

View File

@ -0,0 +1,73 @@
package com.puppycrawl.tools.checkstyle;
import com.puppycrawl.tools.checkstyle.checks.UpperEllCheck;
import com.puppycrawl.tools.checkstyle.checks.RightCurlyCheck;
import com.puppycrawl.tools.checkstyle.checks.RightCurlyOption;
public class RightCurlyCheckTest
extends BaseCheckTestCase
{
public RightCurlyCheckTest(String aName)
{
super(aName);
}
public void testDefault()
throws Exception
{
final CheckConfiguration checkConfig = new CheckConfiguration();
checkConfig.setClassname(RightCurlyCheck.class.getName());
final Checker c = createChecker(checkConfig);
final String fname = getPath("InputLeftCurlyOther.java");
final String[] expected = {
"25:17: '}' should be on the same line.",
"28:17: '}' should be on the same line.",
"40:13: '}' should be on the same line.",
"44:13: '}' should be on the same line.",
};
verify(c, fname, expected);
}
public void testSame()
throws Exception
{
final CheckConfiguration checkConfig = new CheckConfiguration();
checkConfig.setClassname(RightCurlyCheck.class.getName());
checkConfig.addProperty("option", RightCurlyOption.SAME.toString());
final Checker c = createChecker(checkConfig);
final String fname = getPath("InputLeftCurlyOther.java");
final String[] expected = {
"25:17: '}' should be on the same line.",
"28:17: '}' should be on the same line.",
"40:13: '}' should be on the same line.",
"44:13: '}' should be on the same line.",
};
verify(c, fname, expected);
}
public void testAlone()
throws Exception
{
final CheckConfiguration checkConfig = new CheckConfiguration();
checkConfig.setClassname(RightCurlyCheck.class.getName());
checkConfig.addProperty("option", RightCurlyOption.ALONE.toString());
final Checker c = createChecker(checkConfig);
final String fname = getPath("InputLeftCurlyOther.java");
final String[] expected = {
};
verify(c, fname, expected);
}
public void testIgnore()
throws Exception
{
final CheckConfiguration checkConfig = new CheckConfiguration();
checkConfig.setClassname(RightCurlyCheck.class.getName());
checkConfig.addProperty("option", RightCurlyOption.IGNORE.toString());
final Checker c = createChecker(checkConfig);
final String fname = getPath("InputLeftCurlyOther.java");
final String[] expected = {
};
verify(c, fname, expected);
}
}