improved resource bundle handling:

- plugins can use their own bundle (location determined automatically)
- return the message key if ResourceBundle is not available
- added log helper methods in Check.java
This commit is contained in:
Lars Kühne 2002-09-18 05:08:34 +00:00
parent 18ce1a9f66
commit 4880b50a3a
5 changed files with 216 additions and 32 deletions

View File

@ -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++;
}

View File

@ -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";
}
}

View File

@ -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 <code>LocalizedMessage</code> 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 **/

View File

@ -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 <code>LocalizedMessages</code> 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)

View File

@ -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);
}
;