added support for jdk 1.4 assert statements
grammar changes inspired by John Pybus on the antlr-interest mailing list, see http://groups.yahoo.com/group/antlr-interest/message/4968 the changes to Checker.java are not very clean, but I don't see a better solution unless the ANTLR api is improved (compilationUnit() should be an abstract member of Parser, error reporting should be pluggable)
This commit is contained in:
parent
4a859be12a
commit
e2ec464f27
16
build.xml
16
build.xml
|
|
@ -73,8 +73,8 @@
|
|||
<!-- Checks whether the grammar file is newer that the generated code -->
|
||||
<target name="check.antlr">
|
||||
<uptodate property="uptodate.antlr"
|
||||
targetfile="${checkstyle.dir}/GeneratedJavaLexer.java" >
|
||||
<srcfiles dir= "${checkstyle.dir}" includes="java.g"/>
|
||||
targetfile="${checkstyle.dir}/GeneratedJava14Lexer.java" >
|
||||
<srcfiles dir= "${checkstyle.dir}" includes="java.g,java14.g"/>
|
||||
</uptodate>
|
||||
</target>
|
||||
|
||||
|
|
@ -88,6 +88,14 @@
|
|||
dir="${checkstyle.dir}">
|
||||
<arg value="java.g" />
|
||||
</java>
|
||||
<java classname="antlr.Tool"
|
||||
classpath="${antlr-tools.jar}"
|
||||
fork="yes"
|
||||
dir="${checkstyle.dir}">
|
||||
<arg value="-glib" />
|
||||
<arg value="java.g" />
|
||||
<arg value="java14.g" />
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- -->
|
||||
|
|
@ -105,12 +113,16 @@
|
|||
todir="classes/checkstyle"/>
|
||||
</target>
|
||||
|
||||
<!-- Compiles only the test code. Input files are excluded from
|
||||
compilation, they contain code like assert statements
|
||||
that does not compile on all JDKs -->
|
||||
<target name="compile.tests" depends="compile.checkstyle">
|
||||
<mkdir dir="classes/tests" />
|
||||
<depend srcdir="src/tests" destdir="classes/tests" closure="yes"/>
|
||||
<javac srcdir="src/tests"
|
||||
destdir="classes/tests"
|
||||
deprecation="on" debug="on"
|
||||
excludes="**/*nput*.java"
|
||||
classpathref="tests.buildpath" />
|
||||
</target>
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,95 @@ import org.apache.regexp.RESyntaxException;
|
|||
public class Checker
|
||||
implements Defn
|
||||
{
|
||||
|
||||
/**
|
||||
* Overrides ANTLR error reporting so we completely control
|
||||
* checkstyle's output during parsing. This is important because
|
||||
* we try parsing with several grammers (with/without support for
|
||||
* <code>assert</code>). We must not write any error messages when
|
||||
* parsing fails because with the next grammar it might succeed
|
||||
* and the user will be confused.
|
||||
*/
|
||||
private class SilentJava14Recognizer extends GeneratedJava14Recognizer
|
||||
{
|
||||
/**
|
||||
* Creates a new <code>SilentJava14Recognizer</code> instance.
|
||||
*
|
||||
* @param aLexer the tokenstream the recognizer operates on.
|
||||
*/
|
||||
private SilentJava14Recognizer(GeneratedJava14Lexer aLexer)
|
||||
{
|
||||
super(aLexer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser error-reporting function, does nothing.
|
||||
* @param aRex the exception to be reported
|
||||
*/
|
||||
public void reportError(RecognitionException aRex)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser error-reporting function, does nothing.
|
||||
* @param aMsg the error message
|
||||
*/
|
||||
public void reportError(String aMsg)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser warning-reporting function, does nothing.
|
||||
* @param aMsg the error message
|
||||
*/
|
||||
public void reportWarning(String aMsg)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides ANTLR error reporting so we completely control
|
||||
* checkstyle's output during parsing.
|
||||
*
|
||||
* @see SilentJava14Recognizer
|
||||
*/
|
||||
private class SilentJavaRecognizer extends GeneratedJavaRecognizer
|
||||
{
|
||||
/**
|
||||
* Creates a new <code>SilentJavaRecognizer</code> instance.
|
||||
*
|
||||
* @param aLexer the tokenstream the recognizer operates on.
|
||||
*/
|
||||
private SilentJavaRecognizer(GeneratedJavaLexer aLexer)
|
||||
{
|
||||
super(aLexer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser error-reporting function, does nothing.
|
||||
* @param aRex the exception to be reported
|
||||
*/
|
||||
public void reportError(RecognitionException aRex)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser error-reporting function, does nothing.
|
||||
* @param aMsg the error message
|
||||
*/
|
||||
public void reportError(String aMsg)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser warning-reporting function, does nothing.
|
||||
* @param aMsg the error message
|
||||
*/
|
||||
public void reportWarning(String aMsg)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/** configuration */
|
||||
private final Configuration mConfig;
|
||||
|
||||
|
|
@ -140,15 +229,38 @@ public class Checker
|
|||
try {
|
||||
fireFileStarted(aFileName);
|
||||
final String[] lines = getLines(aFileName);
|
||||
VerifierSingleton.getInstance().clearMessages();
|
||||
VerifierSingleton.getInstance().setLines(lines);
|
||||
final Reader sar = new StringArrayReader(lines);
|
||||
final GeneratedJavaLexer jl = new GeneratedJavaLexer(sar);
|
||||
jl.setFilename(aFileName);
|
||||
final GeneratedJavaRecognizer jr = new GeneratedJavaRecognizer(jl);
|
||||
jr.setFilename(aFileName);
|
||||
jr.setASTNodeClass(MyCommonAST.class.getName());
|
||||
jr.compilationUnit();
|
||||
try {
|
||||
VerifierSingleton.getInstance().clearMessages();
|
||||
VerifierSingleton.getInstance().setLines(lines);
|
||||
final Reader sar = new StringArrayReader(lines);
|
||||
final GeneratedJava14Lexer jl = new GeneratedJava14Lexer(sar);
|
||||
jl.setFilename(aFileName);
|
||||
final GeneratedJava14Recognizer jr =
|
||||
new SilentJava14Recognizer(jl);
|
||||
jr.setFilename(aFileName);
|
||||
jr.setASTNodeClass(MyCommonAST.class.getName());
|
||||
jr.compilationUnit();
|
||||
}
|
||||
catch (RecognitionException re) {
|
||||
|
||||
// Parsing might have failed because the checked
|
||||
// filecontains "assert" statement. Retry with a
|
||||
// grammar that treats "assert" as an identifier
|
||||
// and not as a keyword
|
||||
|
||||
// Arghh - the pain - duplicate code!
|
||||
|
||||
VerifierSingleton.getInstance().clearMessages();
|
||||
VerifierSingleton.getInstance().setLines(lines);
|
||||
final Reader sar = new StringArrayReader(lines);
|
||||
final GeneratedJavaLexer jl = new GeneratedJavaLexer(sar);
|
||||
jl.setFilename(aFileName);
|
||||
final GeneratedJavaRecognizer jr =
|
||||
new GeneratedJavaRecognizer(jl);
|
||||
jr.setFilename(aFileName);
|
||||
jr.setASTNodeClass(MyCommonAST.class.getName());
|
||||
jr.compilationUnit();
|
||||
}
|
||||
errors = VerifierSingleton.getInstance().getMessages();
|
||||
}
|
||||
catch (FileNotFoundException fnfe) {
|
||||
|
|
|
|||
|
|
@ -535,7 +535,15 @@ compoundStatement[MyCommonAST[] aCurlies]
|
|||
;
|
||||
|
||||
|
||||
// This production provides a slot for adding additional statement productions.
|
||||
// It is used to simplify an inherited grammar that includes assert statements
|
||||
// (new Java language feature in JDK 1.4)
|
||||
statement[int[] aType, MyCommonAST[] aCurlies]
|
||||
: traditionalStatement[aType, aCurlies]
|
||||
;
|
||||
|
||||
// a traditional (JDK < 1.4) java statement, assert keyword is not allowed
|
||||
traditionalStatement[int[] aType, MyCommonAST[] aCurlies]
|
||||
{
|
||||
final MyModifierSet modSet = new MyModifierSet();
|
||||
final int[] stmtType = new int[1];
|
||||
|
|
@ -676,9 +684,6 @@ statement[int[] aType, MyCommonAST[] aCurlies]
|
|||
|
||||
// empty statement
|
||||
| s:SEMI {#s.setType(EMPTY_STAT);}
|
||||
|
||||
// assert statement
|
||||
// | "assert"^ expression (COLON^ expression)? SEMI!
|
||||
;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// checkstyle: Checks Java source code for adherence to a set of rules.
|
||||
// Copyright (C) 2001-2002 Oliver Burn
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
header {
|
||||
package com.puppycrawl.tools.checkstyle;
|
||||
}
|
||||
|
||||
|
||||
/** Java 1.4 Recognizer
|
||||
*
|
||||
* Based heavily on the Grammer example that comes with ANTLR. See
|
||||
* http://www.antlr.org.
|
||||
*
|
||||
*/
|
||||
class GeneratedJava14Recognizer extends GeneratedJavaRecognizer;
|
||||
|
||||
// Options don't get inherited, copy of option block required.
|
||||
options {
|
||||
k = 2; // two token lookahead
|
||||
exportVocab=GeneratedJava14; // Call its vocabulary "GeneratedJava14"
|
||||
codeGenMakeSwitchThreshold = 2; // Some optimizations
|
||||
codeGenBitsetTestThreshold = 3;
|
||||
defaultErrorHandler = false; // Don't generate parser error handlers
|
||||
buildAST = true;
|
||||
}
|
||||
|
||||
// overrides the statement production in java.g, adds assertStatement
|
||||
statement[int[] aType, MyCommonAST[] aCurlies]
|
||||
: traditionalStatement[aType, aCurlies]
|
||||
| assertStatement[aType, aCurlies]
|
||||
;
|
||||
|
||||
// assert statement, available since JDK 1.4
|
||||
assertStatement[int[] aType, MyCommonAST[] aCurlies]
|
||||
{
|
||||
final MyModifierSet modSet = new MyModifierSet();
|
||||
final int[] stmtType = new int[1];
|
||||
final MyCommonAST[] stmtBraces = new MyCommonAST[2];
|
||||
stmtType[0] = STMT_OTHER;
|
||||
}
|
||||
: ASSERT^ expression ( COLON! expression )? SEMI!
|
||||
;
|
||||
|
||||
class GeneratedJava14Lexer extends GeneratedJavaLexer;
|
||||
|
||||
options {
|
||||
exportVocab=GeneratedJava14; // call the vocabulary "GeneratedJava14"
|
||||
testLiterals=false; // don't automatically test for literals
|
||||
k=4; // four characters of lookahead
|
||||
charVocabulary='\u0003'..'\uFFFF';
|
||||
codeGenBitsetTestThreshold=20;
|
||||
}
|
||||
|
||||
tokens {
|
||||
ASSERT="assert";
|
||||
}
|
||||
|
||||
// antlr expects a definition here: 'unexpected token: null'
|
||||
// To avoid that message, one definition from GeneratedJavaLexer
|
||||
// is repeated. Rather inelegant but I didn't find a better solution :-(
|
||||
// Feel free to improve this...
|
||||
protected
|
||||
FLOAT_SUFFIX
|
||||
: 'f'|'F'|'d'|'D'
|
||||
;
|
||||
|
|
@ -136,4 +136,25 @@ class InputWhitespace
|
|||
o . toString();
|
||||
return o.toString();
|
||||
}
|
||||
|
||||
/** assert statement test */
|
||||
public void assertTest()
|
||||
{
|
||||
// OK
|
||||
assert true;
|
||||
|
||||
// OK
|
||||
assert true : "Whups";
|
||||
|
||||
// evil colons, should be OK
|
||||
assert "OK".equals(null) ? false : true : "Whups";
|
||||
|
||||
// WS tests for assert not implemented yet
|
||||
|
||||
// missing WS around assert
|
||||
// assert(true);
|
||||
|
||||
// missing WS around colon
|
||||
// assert true:"Whups";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue