diff --git a/build.xml b/build.xml
index 144d91c34..21675b1e1 100644
--- a/build.xml
+++ b/build.xml
@@ -73,8 +73,8 @@
-
+ targetfile="${checkstyle.dir}/GeneratedJava14Lexer.java" >
+
@@ -88,6 +88,14 @@
dir="${checkstyle.dir}">
+
+
+
+
+
@@ -105,12 +113,16 @@
todir="classes/checkstyle"/>
+
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
index 6e8ce062a..0e3edbd93 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
@@ -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
+ * assert). 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 SilentJava14Recognizer 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 SilentJavaRecognizer 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) {
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/java.g b/src/checkstyle/com/puppycrawl/tools/checkstyle/java.g
index 712e055ba..17526fd53 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/java.g
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/java.g
@@ -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!
;
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/java14.g b/src/checkstyle/com/puppycrawl/tools/checkstyle/java14.g
new file mode 100644
index 000000000..897ae9dcb
--- /dev/null
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/java14.g
@@ -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'
+ ;
diff --git a/src/tests/com/puppycrawl/tools/checkstyle/InputWhitespace.java b/src/tests/com/puppycrawl/tools/checkstyle/InputWhitespace.java
index f3a6b3ae6..ad4a8be66 100644
--- a/src/tests/com/puppycrawl/tools/checkstyle/InputWhitespace.java
+++ b/src/tests/com/puppycrawl/tools/checkstyle/InputWhitespace.java
@@ -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";
+ }
}