diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
index 3252ea5f4..bf75cf428 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java
@@ -224,21 +224,21 @@ public class Checker
}
catch (FileNotFoundException fnfe) {
errors = new LocalizedMessage[] {
- new LocalizedMessage(0, "general.fileNotFound", null)};
+ new LocalizedMessage(0, "general.fileNotFound", null, null)};
}
catch (IOException ioe) {
errors = new LocalizedMessage[] {
- new LocalizedMessage(0, "general.exception",
+ new LocalizedMessage(0, "general.exception", null,
new String[] {ioe.getMessage()})};
}
catch (RecognitionException re) {
errors = new LocalizedMessage[] {
- new LocalizedMessage(0, "general.exception",
+ new LocalizedMessage(0, "general.exception", null,
new String[] {re.getMessage()})};
}
catch (TokenStreamException te) {
errors = new LocalizedMessage[] {
- new LocalizedMessage(0, "general.exception",
+ new LocalizedMessage(0, "general.exception", null,
new String[] {te.getMessage()})};
}
@@ -276,7 +276,7 @@ public class Checker
fireFileStarted(docFile);
if (!packageDoc.exists()) {
final LocalizedMessage error =
- new LocalizedMessage(0, "javadoc.packageHtml", null);
+ new LocalizedMessage(0, "javadoc.packageHtml", null, null);
fireErrors(docFile, new LocalizedMessage[]{error});
packageHtmlErrors++;
}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java
index 8fcbbd6d7..0c70585e4 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java
@@ -28,6 +28,9 @@ import java.util.Map;
*/
public abstract class Check
{
+ /** resuable constant for message formating */
+ private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+
/** name to store lines under */
private static final String LINES_ATTRIBUTE = "lines";
/** name to store filename under */
@@ -170,7 +173,7 @@ public abstract class Check
* Set the lines associated with the tree.
* @param aLines the file contents
*/
- public void setLines(String[] aLines)
+ public final void setLines(String[] aLines)
{
getTreeContext().put(LINES_ATTRIBUTE, aLines);
}
@@ -179,7 +182,7 @@ public abstract class Check
* Returns the lines associated with the tree.
* @return the file contents
*/
- public String[] getLines()
+ protected final String[] getLines()
{
return (String[]) getTreeContext().get(LINES_ATTRIBUTE);
}
@@ -188,7 +191,7 @@ public abstract class Check
* Set the name of the file associated with the tree.
* @param aFilename the file name
*/
- public void setFilename(String aFilename)
+ public final void setFilename(String aFilename)
{
getTreeContext().put(FILENAME_ATTRIBUTE, aFilename);
}
@@ -197,15 +200,120 @@ public abstract class Check
* Returns the filename associated with the tree.
* @return the file name
*/
- public String getFilename()
+ protected final String getFilename()
{
return (String) getTreeContext().get(FILENAME_ATTRIBUTE);
}
- /** @see needs to be fixed */
- public void log(int aLine, String aMessage)
+ /**
+ * Log an error message.
+ *
+ * @param aLine the line number where the error was found
+ * @param aKey the message that describes the error
+ */
+ protected final void log(int aLine, String aKey)
{
- final String fname = (String) getTreeContext().get(FILENAME_ATTRIBUTE);
- System.out.println(fname + ":" + aLine + ": " + aMessage);
+ log(aLine, aKey, EMPTY_OBJECT_ARRAY);
+ }
+
+ /**
+ * Log an error message.
+ *
+ * @param aLine the line number where the error was found
+ * @param aKey the message that describes the error
+ * @param aArgs the details of the message
+ *
+ * @see java.text.MessageFormat
+ */
+ protected final void log(int aLine, String aKey, Object aArgs[])
+ {
+ log(aLine, 0, aKey, aArgs);
+ }
+
+
+ /**
+ * Helper method to log a LocalizedMessage. Column defaults to 0.
+ *
+ * @param aLineNo line number to associate with the message
+ * @param aKey key to locale message format
+ * @param aArg0 first argument
+ */
+ public void log(int aLineNo, String aKey, Object aArg0)
+ {
+ log(aLineNo, aKey, new Object[] {aArg0});
+ }
+
+ /**
+ * Helper method to log a LocalizedMessage. Column defaults to 0.
+ *
+ * @param aLineNo line number to associate with the message
+ * @param aKey key to locale message format
+ * @param aArg0 first argument
+ * @param aArg1 second argument
+ */
+ public void log(int aLineNo, String aKey, Object aArg0, Object aArg1)
+ {
+ log(aLineNo, aKey, new Object[] {aArg0, aArg1});
+ }
+
+ /**
+ * Helper method to log a LocalizedMessage. Column defaults to 0.
+ *
+ * @param aLineNo line number to associate with the message
+ * @param aKey key to locale message format
+ * @param aArg0 first argument
+ * @param aArg1 second argument
+ * @param aArg2 third argument
+ */
+ public void log(int aLineNo, String aKey,
+ Object aArg0, Object aArg1, Object aArg2)
+ {
+ log(aLineNo, aKey, new Object[] {aArg0, aArg1, aArg2});
+ }
+
+
+ /**
+ * Helper method to log a LocalizedMessage.
+ *
+ * @param aLineNo line number to associate with the message
+ * @param aColNo column number to associate with the message
+ * @param aKey key to locale message format
+ * @param aArgs arguments for message
+ */
+ public void log(int aLineNo, int aColNo, String aKey, Object[] aArgs)
+ {
+ final String fname = getFilename();
+ System.out.println(fname + ":" + aLineNo + ": " + aKey);
+
+ final int col = aColNo + 1;
+// final int col = 1 + Utils.lengthExpandedTabs(
+// mLines[aLineNo - 1], aColNo, mTabWidth);
+ mMessages.add(new LocalizedMessage(
+ aLineNo, col, getResourceBundle(), aKey, aArgs));
+ }
+
+
+ /**
+ * TODO: Should this method be protected or should we keep the api simple?
+ * Returns the name of a a resource bundle that contains the messages
+ * used by this check.
+ *
+ * The default implementation expects the resource files to be named
+ * messages.properties, messages_de.properties, etc. The file should
+ * be placed in the same package as the Check implementation.
+ *
+ * Example: If you write com/foo/MyCoolCheck, create resource files
+ * com/foo/messages.properties, com/foo/messages_de.properties, etc.
+ *
+ * @return name of a resource bundle that contains the messages
+ * used by this check
+ */
+ private String getResourceBundle()
+ {
+ // PERF: check perf impact, maybe cache result
+ final String className = this.getClass().getName();
+ final String packageName =
+ className.substring(className.lastIndexOf('.') + 1);
+ return packageName + "." + "messages";
}
}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java
index 24225b530..9bcae5f28 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java
@@ -18,8 +18,13 @@
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle.api;
+// TODO: check that this class is in the right package
+// as soon as architecture has settled. At the time of writing
+// this class is not necessary as a part of the public api
+
import java.util.ResourceBundle;
import java.util.Locale;
+import java.util.MissingResourceException;
import java.text.MessageFormat;
/**
@@ -33,10 +38,6 @@ import java.text.MessageFormat;
public class LocalizedMessage
implements Comparable
{
- /** name of the resource bundle to get messages from **/
- private static final String MESSAGE_BUNDLE =
- "com.puppycrawl.tools.checkstyle.messages";
-
/** the locale to localise messages to **/
private static Locale sLocale = Locale.getDefault();
@@ -51,16 +52,22 @@ public class LocalizedMessage
/** arguments for MessageFormat **/
private final Object[] mArgs;
+ /** name of the resource bundle to get messages from **/
+ private final String mBundle;
+
+
/**
* Creates a new LocalizedMessage instance.
*
* @param aLineNo line number associated with the message
* @param aColNo column number associated with the message
+ * @param aBundle resource bundle name
* @param aKey the key to locate the translation
* @param aArgs arguments for the translation
*/
public LocalizedMessage(int aLineNo,
int aColNo,
+ String aBundle,
String aKey,
Object[] aArgs)
{
@@ -68,6 +75,7 @@ public class LocalizedMessage
mColNo = aColNo;
mKey = aKey;
mArgs = aArgs;
+ mBundle = aBundle;
}
/**
@@ -75,25 +83,36 @@ public class LocalizedMessage
* defaults to 0.
*
* @param aLineNo line number associated with the message
+ * @param aBundle name of a resource bundle that contains error messages
* @param aKey the key to locate the translation
* @param aArgs arguments for the translation
*/
- public LocalizedMessage(int aLineNo, String aKey, Object[] aArgs)
+ public LocalizedMessage(
+ int aLineNo, String aBundle, String aKey, Object[] aArgs)
{
- this(aLineNo, 0, aKey, aArgs);
+ this(aLineNo, 0, aBundle, aKey, aArgs);
}
/** @return the translated message **/
public String getMessage()
{
- // Very simple approach - wait for performance problems.
- // Important to use the default class loader, and not the one in the
- // Configuration object. This is because the class loader in the
- // Configuration is specified by the user for resolving custom classes.
- final ResourceBundle bundle =
- ResourceBundle.getBundle(MESSAGE_BUNDLE, sLocale);
- final String pattern = bundle.getString(mKey);
- return MessageFormat.format(pattern, mArgs);
+ try {
+ // PERF: Very simple approach - wait for performance problems.
+ // Important to use the default class loader, and not the one in the
+ // Configuration object. This is because the class loader in the
+ // Configuration is specified by the user for resolving custom
+ // classes.
+ final ResourceBundle bundle =
+ ResourceBundle.getBundle(mBundle, sLocale);
+ final String pattern = bundle.getString(mKey);
+ return MessageFormat.format(pattern, mArgs);
+ }
+ catch (MissingResourceException ex) {
+ // If the Check author didn't provide i18n resource bundles
+ // and logs error messages directly, this will return
+ // the author's original message
+ return MessageFormat.format(mKey, mArgs);
+ }
}
/** @return the line number **/
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessages.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessages.java
index de0209a32..ec20e6e09 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessages.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessages.java
@@ -18,6 +18,10 @@
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle.api;
+// TODO: check that this class is in the right package
+// as soon as architecture has settled. At the time of writing
+// this class is not necessary as a part of the public api
+
import java.util.Collections;
import java.util.ArrayList;
@@ -34,6 +38,8 @@ public class LocalizedMessages
private final int mTabWidth;
/** the lines of the file being checked **/
private String[] mLines;
+ private static final String OLD_BUNDLE =
+ "com.puppycrawl.tools.checkstyle.messages";
/**
* Creates a new LocalizedMessages instance.
@@ -75,16 +81,21 @@ public class LocalizedMessages
mMessages.add(aMsg);
}
+ // TODO: remove the add() methods below and the OLD_BUNDLE constant
+ // this has to wait until they are not referenced by Verifier any more
+
/**
* Helper method to log a LocalizedMessage. Column defaults to 0.
*
* @param aLineNo line number to associate with the message
* @param aKey key to locale message format
* @param aArgs arguments for message
+ *
+ * @deprecated replaced by Check.log()
*/
public void add(int aLineNo, String aKey, Object[] aArgs)
{
- add(new LocalizedMessage(aLineNo, 0, aKey, aArgs));
+ add(new LocalizedMessage(aLineNo, 0, OLD_BUNDLE, aKey, aArgs));
}
/**
@@ -92,6 +103,8 @@ public class LocalizedMessages
*
* @param aLineNo line number to associate with the message
* @param aKey key to locale message format
+ *
+ * @deprecated replaced by Check.log()
*/
public void add(int aLineNo, String aKey)
{
@@ -104,6 +117,8 @@ public class LocalizedMessages
* @param aLineNo line number to associate with the message
* @param aKey key to locale message format
* @param aArg0 first argument
+ *
+ * @deprecated replaced by Check.log()
*/
public void add(int aLineNo, String aKey, Object aArg0)
{
@@ -117,6 +132,8 @@ public class LocalizedMessages
* @param aKey key to locale message format
* @param aArg0 first argument
* @param aArg1 second argument
+ *
+ * @deprecated replaced by Check.log()
*/
public void add(int aLineNo, String aKey, Object aArg0, Object aArg1)
{
@@ -131,6 +148,8 @@ public class LocalizedMessages
* @param aArg0 first argument
* @param aArg1 second argument
* @param aArg2 third argument
+ *
+ * @deprecated replaced by Check.log()
*/
public void add(int aLineNo, String aKey,
Object aArg0, Object aArg1, Object aArg2)
@@ -145,12 +164,15 @@ public class LocalizedMessages
* @param aColNo column number to associate with the message
* @param aKey key to locale message format
* @param aArgs arguments for message
+ *
+ * @deprecated replaced by Check.log()
*/
public void add(int aLineNo, int aColNo, String aKey, Object[] aArgs)
{
final int col = 1 + Utils.lengthExpandedTabs(
mLines[aLineNo - 1], aColNo, mTabWidth);
- mMessages.add(new LocalizedMessage(aLineNo, col, aKey, aArgs));
+ mMessages.add(
+ new LocalizedMessage(aLineNo, col, OLD_BUNDLE, aKey, aArgs));
}
/**
@@ -159,6 +181,8 @@ public class LocalizedMessages
* @param aLineNo line number to associate with the message
* @param aColNo column number to associate with the message
* @param aKey key to locale message format
+ *
+ * @deprecated replaced by Check.log()
*/
public void add(int aLineNo, int aColNo, String aKey)
{
@@ -172,6 +196,8 @@ public class LocalizedMessages
* @param aColNo column number to associate with the message
* @param aKey key to locale message format
* @param aArg0 first argument
+ *
+ * @deprecated replaced by Check.log()
*/
public void add(int aLineNo, int aColNo, String aKey, Object aArg0)
{
@@ -186,6 +212,8 @@ public class LocalizedMessages
* @param aKey key to locale message format
* @param aArg0 first argument
* @param aArg1 second argument
+ *
+ * @deprecated replaced by Check.log()
*/
public void add(int aLineNo, int aColNo, String aKey,
Object aArg0, Object aArg1)
@@ -202,6 +230,8 @@ public class LocalizedMessages
* @param aArg0 first argument
* @param aArg1 second argument
* @param aArg2 third argument
+ *
+ * @deprecated replaced by Check.log()
*/
void add(int aLineNo, int aColNo, String aKey,
Object aArg0, Object aArg1, Object aArg2)
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/java_new.g b/src/checkstyle/com/puppycrawl/tools/checkstyle/java_new.g
index 8cf10ddaa..e0b9bb67a 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/java_new.g
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/java_new.g
@@ -51,6 +51,7 @@ tokens {
STRICTFP="strictfp"; SUPER_CTOR_CALL; CTOR_CALL;
}
+
// Compilation Unit: In Java, this is a single file. This is the start
// rule for this parser
compilationUnit
@@ -927,6 +928,24 @@ options {
codeGenBitsetTestThreshold=20;
}
+// JavaLexer verbatim source code
+{
+
+ // explicitly set tab width to 1 (default in ANTLR 2.7.1)
+ // in ANTLR 2.7.2a2 the default has changed from 1 to 8
+ public void tab()
+ {
+ setColumn( getColumn() + 1 );
+ }
+
+ private CommentManager mCommentManager = null;
+
+ void setCommentManager(CommentManager aCommentManager)
+ {
+ mCommentManager = aCommentManager;
+ }
+
+}
// OPERATORS
@@ -995,14 +1014,18 @@ WS : ( ' '
// Single-line comments
SL_COMMENT
- : "//"
+ : "//" { mCommentManager.reportCPPComment(getLine(), getColumn() - 3); }
(~('\n'|'\r'))* ('\n'|'\r'('\n')?)
{$setType(Token.SKIP); newline();}
;
// multiple-line comments
ML_COMMENT
- : "/*"
+{
+ int startLine;
+ int startCol;
+}
+ : "/*" { startLine = getLine(); startCol = getColumn() - 3; }
( /* '\r' '\n' can be matched in one alternative or by matching
'\r' in one iteration and '\n' in another. I am trying to
handle any flavor of newline that comes in, but the language
@@ -1021,7 +1044,11 @@ ML_COMMENT
| ~('*'|'\n'|'\r')
)*
"*/"
- {$setType(Token.SKIP);}
+ {
+ mCommentManager.reportCComment(startLine, startCol,
+ getLine(), getColumn() - 2);
+ $setType(Token.SKIP);
+ }
;